[TSTIL] The easee Wizard Engine

[ This is a part of "The Software That I Love", a series of posts about Software that I created or had a small part in ]

2018 - The easee Wizard Engine

After almost 7 years at Mendix I got a bit restless. My product Mendix Cloud v4 had launched, the big engineering behind it was done and the endless on-call duty was tiring me out. I felt ready for something new. Being addicted to Hacker News I badly wanted to join or start a real startup. A lot was happening. My friend Erik was going to start Soulpicks. Mohsen had some idea with luggage tracking. Rik left for a crazy eye testing startup. Dennis was starting Blockbax with Roy. I talked to some of them about starting something together, but nothing panned out. I had a family and a mortgage, and being the sole breadwinner my personal burn-rate was quite high.

Then I got a message from Rik, who was now the lead unicorn engineer at easee. "We're looking for a CTO. Do you maybe know anyone?" Well, no, but I was interested! A couple of months, sleepless nights and a thorough interview process later, I was the CTO. We were a bit worried about the non-compete with Mendix, but it turned out fine. These things are not really enforceable anyway. This was a hip startup in Amsterdam, exactly what I wanted. Getting in I realized we only had a month or two of runway. The only way to raise some funding was with a CTO in the team, and we needed the funding to pay me. A classic catch-22.

Even before I started full-time I joined for a couple of investor calls, made my first hire (Francesco) and had an epic party after the quarterly kick-off. I'm still banned from dancing on stage at the Chin-Chin club in Amsterdam. This was all new and super exciting to me. Yves, the CEO, was new to startups too, but having an MBA under his belt and a lot of corporate experience was a lot more experienced than I was.

I took 0 days off between Mendix and easee. In hindsight that was not healthy, but we had 3 urgent problems to solve.
  1. Funding.
  2. Scalability. V1 of the eye test would crash with about 10 concurrent users. There was a spike of users after we got on RTL Nieuws and the database did not look pretty after that.
  3. The performance of our cylinder test. A clinical study was underway in the UMC Utrecht, and things looked good, except for the cylinder test. We had a new one but needed to implement it.
We divided and conquered. Yves was naturally on funding (as he has been ever since ;) ). I was on scalability and re-architecture. Rik and Francesco were a couple months more experienced in eye testing and took on the cylinder test. They built this on the new architecture that I was building.

The easee online eye exam is fundamentally a big wizard (plus lots of clever algorithms in the back-end of course). It was implemented as a state machine in the database. Every click went through the state machine in the back-end, a classic MVC in Laravel. This was slow and did not scale because the database architecture was a mess. With a client-server architecture we could never get to sub 100ms responsiveness. I decided to go for a Single Page App built with Vue, with most of the logic of the wizard in the front-end. I had no experience with Vue, but loved its pragmatism. Now I had to figure out how to create a simple engine for displaying the screens in the correct order.

We needed to show screens one after another, and depending on the input of the user, go through a different path in the wizard. We could simply point the "next" button to the next screen. But some screens were re-used, so that was a no-go or we'd get a loop. I felt like the code would get messy, but there had to be a clean solution. It took weeks of banging my head against the wall, but then it clicked. I learned how async/await worked (I never understood it before). I realized the logic of a wizard is just a classic program. Each screen has input (the props) and output (whatever the user selects). If we wrap this in a promise we can "await" the user's action. Instead of "awaiting" a database or remote server, we await the action of the user. I thought this was extremely clever.

So that's what I built. A small engine of about 100 lines of code that can show a screen, await the user's action on it and return the output to the main program logic. It can serialize the data and store it in session storage so that you can safely reload the browser. The serialization also allows the state to be sent to another device and continue there. I can't share much more details, but it's really cool. 

This simple engine allowed the developers in the team to just work on the screens and keep the codebase clean. It also made the flow of the eye exam easy to understand, as it's just a program with functions, output and variables.

We quickly rebuilt the exact same product as v1 on the new engine. Then we added the new cylinder test and launched the second part of the clinical study with it. Yves managed to raise a good seed round with Nimbus Ventures. All of this within 4 months of me joining. In November 2018 we put v1.5 of the product live with the new engine. Since then it has powered hundreds of thousands of eye tests and had almost no bugs. I am very proud of the easee wizard engine.


Popular posts from this blog

AI programming tools should be added to the Joel Test

The unreasonable effectiveness of i3, or: ten years of a boring desktop environment

The long long tail of AI applications