One Year of MVP
Hello everyone!
It’s been a while. What started as a weekly log of building Chiffre and following the 100 Days of Tech Startup challenge ended up stalling last July.
Life gets in the way. Obviously, 2020 did make things more difficult for everyone, and in my case (I won’t bother you too long with my life, I promise) I took some time off software development in the summer to move into a new home with my wife. Silver lining: we became first-time parents in November, and it’s been quite the ride ever since. 👶🍼💩
If you’re a new subscriber (a lot of you have joined in since the last issue), 👋 hello, thanks for joining in and welcome to the only weekly newsletter that runs twice a year. At least you can’t complain about spam.
Quick recap: Chiffre is an end-to-end encrypted web analytics side-project of mine, that I’m trying to turn into a SaaS product, publishing what I learn (mostly in the form of mistakes) along the way.
One Year of MVP
The first deployment of the Chiffre.io MVP came online in February 2020. By MVP, I mean:
- Minimum: it works, in the sense that it collects end-to-end encrypted data points and shows them on a dashboard. But not very minimalist in architecture, more on that below.
- Viable: it works without me working on it. Automatic security updates, CI/CD everywhere and automatic maintenance by Clever Cloud. It costs a bit, but it’s worth it, more on that later.
- Project, not Product. Product would assume there’s a payment system somewhere, there is none at the time of writing.
Ideally, MVP should mean:
- Minimum: it works for users, it lets them see useful stats and extract meaning from their analytics. At the moment the user-side part is the one that has had the least work done. For two reasons: doubt about the product and too strong an initial focus on back-end and security aspects, followed by a pit of motivation (the 2020 effect).
- Viable: working on its own is great. Having it pay for itself would be amazing. Monetary viability and profitability is the ultimate goal of any project, otherwise we’re just doing charity work.
- Product, not Project. This implies solving a need for customers. This is the part where I have the least experience. I know how to build things, but selling before building is a strange concept that I will have to familiarise myself with.
So after one year of operations, Chiffre has cost me (from my own pocket):
- 12 months of Node.js services running, at 6€/month per service, two services at any time (the event aggregator and the main backend / API) ⇒ ~145€
- 12 months of Redis, used as a queue between both services, 10€/month ⇒ 120€
- Domain name: 35€ (now the price for .io has increased to 45€).
- PostgreSQL database: free (120 MiB used out of 256 MiB on the free tier)
Total: ~300€
The Cost of Hype Driven Architecture
Or “Microservices are a footgun”.
In retrospect, having a separate service for the event aggregation + a Redis queue + the main backend was overkill. There were a few “reasons” behind this choice:
- The backend is not yet open-source, having the event aggregator public is easier to show “no tricks up my sleeve”. Transparency is key with E2EE, but here it’s only half-assed.
- Reducing the attack surface: by having a smaller service be the interface with customers’ websites, I reduce the possibility of misuse. Both for me and the customer’s website. Kind of relevant, as I saw lots of bot traffic trying to sniff Wordpress login routes and other kind of automated vulnerability scanning.
- Scaling: ahh, the myth of “but my service should scale to thousands of requests per second”. Not relevant at all when serving 10 clients. Even when trending on Hacker News, I’ve never had to move either service past the minimum scaler/dyno/droplet/unitOfComputing size.
- Performance: initially, I found that writing events to PostgreSQL directly was much slower than pushing them into a Redis queue, so I did the latter to let the event aggregator return early and not cause bottlenecks. But again, this is trying to solve a scaling problem that does not exist, and there are bottlenecks with queue processing as well. Also, since the aggregator returns nothing, it does not matter for website reactivity (events are sent with
navigator.sendBeacon
which is non-blocking and low-priority).
It would have cost me less money to have it all as a single Node.js service, no Redis. Lesson learned: monoliths still rule, and Hype Driven Development is costly (in both time, money and induced technical debt, which translates back to time and money).
Adventures in Front-End Performance
Or “How the wrong turn can bring React to its knees”
Decryption takes time. Like, a lot more time than downloading the encrypted events from the server. This is due to the fact that I use a JavaScript implementation of NaCl, maybe WebAssembly could help here, but that’s another problem.
Our story concerns where to do things. When I first implemented the download + decrypt + store layer, it all lived in the React render function. Simple: time range props change, run a useEffect
, load everything, decrypt everything, store everything.
Needless to say, when there are a lot of messages to process (long time since last login or peak of traffic), this slows down the UI thread to a halt. Yep: when JavaScript is busy running a side-effect, it does not process UI events.
In my last newsletter issue, I was working on moving the download + decrypt + store layer to a WebWorker. That worked fine, but now the bottleneck is on the analytics aggregation part (digesting raw data into leaderboards and useful stats), so it will also probably have to go to a Worker as well.
Show Some Stats, Silly
- 157 200 events processed
- 11 users, me + 3 other active users and 7 churned
- 21 websites (7 of mine, 14 of others)
- 2 viral peaks, one by Mike Nikles’ release of his book on Cloud Native Development, the other last week when one of my cryptographic toys reached front page on Hacker News.
- 180 countries (between 72 and 92% of world coverage, depending on your political views). Includes some visits from Tor users. Hello there, privacy-loving friends! 👋
Running some back of the envelope calculations, this amounts to 0.002€ per event. I’m pretty sure a serverless approach would cost me less.
Features added
Even though I’ve been busy changing nappies while juggling with freelancing contracts, I have managed to add a few things to the MVP since the last publication:
Custom Events
Those were supported since day one, but had no visualisation of their own yet. Currently they only show as a history table, but I’d like to add a leaderboard view there too. I use them to track what plans are selected on the landing page:
Oh, another good lesson learned here: some people actually clicked on the paid plans. 20 people selected the small plan, and 4 selected the large plan. But since I’ve been procrastinating to implement a payment system, I’ve potentially missed out on 5 240€. Yeah, I know. 🤦♂️
Data Export
Since all the clear-text data lives in the browser, in the IndexedDB database, it’s easy to export your raw analytics data points to a newline-delimited JSON file.
In the future, I might add expiration dates on the encrypted events on the server for free plans, since all the decrypted data is local it would only be a penalty if wanting to sync a new device (that would have to download a larger history of encrypted events), and the data export could help there at no cost for me.
The Future ?
My brief drive-by on Hacker News attracted some attention to Chiffre, and I was contacted by members of the Fission project, a decentralised community with whom I’ll be doing a live-streamed video chat to present Chiffre. I’ll post it in here once it’s out.
As for the product itself, I initially gave myself the goal to ship it (ie: open it to everyone, not just with cryptic invite codes) in Q1 2021. Which is ambitious since I’ve transitioned to a full-stack dad role since my wife’s maternity leave ended. Family comes first, always. So it will ship when it will ship.
There are some showstopper issues that need attention before I send you people some invite codes, like:
- Moving the front-end to another platform. At the moment it’s a static HTML export from Next.js, and this does not play well with dynamic paths, so I’ll move it to Vercel.
- Fix some issues with the tracker script
- Allow projects to be edited. At the moment you have to reach out to change the deployment URL, which is crude for everyone (pun intended).
If you made it this far, sorry for all my bad jokes (hey, I just became a dad, they come with the territory). I can’t say when the next issue will be, but I’d like it to contain signup invites, or even the announcement that “screw it, it’s available for everyone. Just ship it™”.
In the mean time, take care of yourself.
François Best
Founder | Chiffre.io