Different pricing rules. Different payment collection flows. Different backoffice workflows. Frankly, different everything. Making all of it feel like one simple product is where the engineering gets hard and interesting.
Each language here was a deliberate choice to deal with engineering challenges we were facing at that time. Not all bets worked out -- and some were walked back.
First commit. A Rails app with a jQuery front-end.
Booking forms got too dynamic for jQuery, so we reached for AngularJS.
A heads-down, funded focus year -- 3,600 commits and traffic up 140%. Then our servers ran out of memory and we had to double capacity to keep up.
Read the story →Refactoring a large Rails+JS codebase as we learned the market was a major PITA. We wanted a typed language to change the core without fear -- and reached for Haskell: typed, and it forces you to write correct code.
The same typed-safety instinct hit the front-end: Angular v1 + JS was hard to evolve without constant manual testing. Angular 2's real pull was TypeScript -- a typed front-end was exactly what we wanted. But adopting it meant a full framework rewrite, so we backed out. (We'd get the types a better way -- see 2026.)
The separate Haskell service (~34K lines by 2017) folds into the main repo -- which is where its line joins the graph.
Same goal, different route: Elm (typed, pure) for internal admin UI. Peaked around 10K lines, then unwound -- TypeScript on AngularJS ended up giving us the same type-safety without a second front-end stack, and Elm itself had gone a bit quiet as a language. Both Elm and the Angular 2 experiment became redundant.
Near-extinction for a travel SaaS: the industry ran at ~30% of 2019, and didn't fully recover until 2024. Product work slows through 2021-22, but the codebase never stops moving.
As travel cratered, we turned inward: years spent automating our own operations -- billing, CRM, support, internal messaging -- almost all in Haskell, wired to Zoho. It's part of why the Haskell curve keeps climbing right through the COVID trough. → Automation & AI
Server-rendered HTML-over-the-wire, with the UI rendered server-side in Haskell -- tempting, because it would lean even harder on Haskell. But our forms are highly dynamic (the very thing that pushed us off jQuery back in 2013), and Turbo felt like a step backward even with the server doing the rendering. Dropped, not forced.
The newest layer: AI/LLM workflows that read and draft from support tickets, analyse sales calls, and more -- built on top of that Haskell ops-automation. → Automation & AI
The answer to the Angular 2 and Elm dead-ends turned out to be simple: add TypeScript to the AngularJS we already had, and auto-generate the front-end types from our Haskell backend. That Haskell→TypeScript bridge got us 80-90% of the end-to-end type-safety we'd been chasing -- without a full front-end rewrite. TS roughly quadrupled in 2026, and we expect the trend to continue. No Angular 1 to Angular 2 migration. No wholesale rewrite to React.
Overtakes Ruby -- and both are still growing. Haskell just grew faster, rather than replacing anything.
Not a feature we bolted on -- the operating system of a small team. And not a pivot: the AI layer is the next chapter of a decade spent automating our own operations in Haskell.
~8,000 lines of Haskell wiring Zoho, billing, support and chat together.
Ticket triage and answering bots on top of the automation we already ran.
Every release ships AI-drafted notes, emailers and broadcasts.
Libraries we wrote for our own use and are releasing for everyone else's. odd-jobs already runs in production well beyond VacationLabs.
Hiring changed in the last couple of years, and a lot of what used to work just doesn't. A take-home assignment barely tells us anything now -- AI can breeze through it. So can most of the interview questions we used to lean on.
So we've slowed down and gotten specific about what we're looking for. More than any particular stack, we want people who can use AI without being used by it: who treat it as a sharp assistant and keep hold of the reins. You're driving it, not being driven by it.
We don't have a neat process to hand you yet -- we're working that out like everyone else. But if that resonates, email us and tell us how you actually work with these tools.