Forty percent faster,and not one lineof it was a rewrite.
Columbus's platform did too much work on every request, and at peak everything queued behind the same few queries. I led the performance work. No rewrite, no big bang — find what it's actually spending time on, remove that, repeat for eighteen weeks.
- Client
- Columbus Assicurazioni
- Engaged via
- Recognise Design
- Role
- Senior Tech Lead
- Timeline
- Aug 2022 – Nov 2024
- Result
- 40%+ faster
- Live
- Visit site ↗
Slow is a symptom, not a cause
The brief was 'the platform is slow'. It wasn't, uniformly — it was fast until a certain amount of concurrent traffic, at which point everything queued behind the same unindexed reads. Insurance traffic is spiky by nature: a renewal window or a claims event concentrates load into hours. The honest first step was measurement, because the instinct in the room was a rewrite and the data did not support one.
- Peak-hour concurrency stacking behind a small set of expensive queries
- Repeated identical reads going to SQL Server every time
- Synchronous work in the request path that nobody was waiting on
- A rewrite proposal that measurement made unnecessary
A rewrite wasproposed. Thenumbers said no.
The tail was the problem, not the median — which is exactly the shape that makes a platform feel broken while every average looks fine. Measuring it first is what turned a rewrite into eighteen weeks of releases.
Response time by percentile
MILLISECONDS · LOWER IS BETTER
- Before
- After
Where the gain came from
SHARE OF TOTAL IMPROVEMENT
- Query optimisation & indexing44%
- Redis caching on hot reads23%
- Concurrency handling18%
- Work moved to Service Bus15%
No single heroic change. Four ordinary ones, each measured, each shipped on its own.
Queries, cache, and getting work off the request
Most of the 40% came from the database: query optimisation and indexing, fewer round-trips per page, and removing the N+1s that accumulate in any long-lived codebase. Redis took the hot reads so repeated requests stopped touching SQL Server at all. Then concurrency handling, so peak traffic stopped stacking against itself. Finally, anything that didn't need to happen before the response moved onto Azure Service Bus — and SignalR pushed the result to the screen when it finished.
- Query optimisation and indexing — the largest single contribution
- Redis caching for hot reads, with deliberate invalidation
- Concurrency handling so peak load stops queueing behind itself
- Event-driven services on Azure Service Bus for off-request work
- SignalR for live updates as events land
- Public site on Umbraco and .NET, TypeScript on the front
“Measure, change one thing, measure again. Then do it for eighteen weeks.”
How the 40% actually got found
Shipping performance weekly, as tech lead
Performance work fails when it's a project. We ran it as a habit instead: a measured baseline, a weekly target, one change at a time with the number attached, visible to the client. That made the gains auditable and it made the team better at spotting the next one — which matters more than the 40%, because it's the part that stayed after I left.
- Measured baseline before any change, re-measured after each
- One change per release, with its number attached
- Cross-functional team — backend, frontend, DevOps
- OAuth2 / OIDC with Azure AD, and JWT across services
- +40%
- Faster platform, end to end
- 0 rewrites
- The application kept shipping throughout
- 3 layers
- Query, cache and event path
Policies and claims move 40%+ faster and peak traffic stops piling up on itself. The part I'm more pleased about: the team that stayed can now find the next bottleneck without me.
Stack