Modernising an insurance platform without a rewrite
How a fast-growing insurance marketplace moved from server-rendered pages to React and a structured API, one page at a time, while still shipping features to show investors.
Overview
A few years ago I worked with a small B2B SaaS company building a marketplace for business insurance, mainly in Latin America. The platform matched brokers to underwriters and took the friction out of placing cover. Its particular innovation was making smaller premiums viable. Policies that had been too fiddly and costly for anyone to bother with could be quoted and placed quickly, which opened up a part of the market that insurers had never found worth serving.
The system itself was only a few years old, built in Go with server-rendered HTML templates and vanilla JavaScript. As the feature requests grew more complex, the front end was straining. Screens were becoming interactive in ways that templates and hand-written JavaScript handle badly, and the backend had grown without a consistent API or a clear permissions model.
The constraint
It was obvious that the product needed an interactive JavaScript framework on the front end and a structured API with solid permissions behind it. It was equally obvious that a full rewrite wasn’t an option. The business was growing fast and had investors watching. It couldn’t stand still for months while a new version caught up with the old one.
I was asked to design a way through, implement it, and hand it over.
Islands first, then pages
The approach was to let the old and new coexist in the same product. Legacy pages carried on as Go templates. New pages were built in React against the new API. The two had to share routing, authentication and data without users or developers noticing the join.
The first step was getting React running as an island inside an existing page. That took a short while and meant developers could start building new features in React almost immediately, rather than waiting for a platform migration to finish.
From there the design filled in. Routing decided whether a URL was served by Go or by the React app. Authentication was shared, so a session carried across both without a second login. Server data was passed to the app in a consistent shape, and the new API took over as the way React pages talked to the backend. Once that was in place, legacy pages were moved to React one by one, whenever the time was right. A page that needed significant new work was rebuilt. A page that worked fine was left alone.
Permissions
The hardest judgement was the permissions model. Brokers, underwriters and administrators each needed different access, and it was difficult to know in advance how much structure the model needed. Too little and developers would end up hard-coding access checks to cover the gaps. Too much and every feature would be slowed down by it.
My approach was to make a best guess, build it, and use it. Friction in a design like this shows up early, usually within the first few features built against it, and that’s the moment to adjust. The model changed a little after the first real use and then settled.
Outcome
Development got quicker, and by the team’s own account, more enjoyable. Features were released faster. A library of reusable React components built up as pages were migrated, so each new screen took less effort than the last and the UI had more consistency
The whole thing took three months with a team of three. Me, the CTO and a front-end developer. I delivered the final working version and the team took it over.
Delivery
I was responsible for the migration design, the routing, authentication and data-passing mechanism, the API and permissions model, and the first pages built on it, working alongside the CTO and a front-end developer. The hybrid was meant as a bridge, and in hindsight it probably served as the solution for longer than planned! The general argument for staging modernisation this way is set out in Modernising legacy SaaS without a big-bang rewrite.