Skip to content
04Case studyPerformance engineering

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
01The problem

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
Measurement

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
p50−43%
410
232
p95−62%
1,480
560
p99−60%
2,940
1,180
01,0002,0003,000

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.

01The work

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

01How it was led

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
Impact
+40%
Faster platform, end to end
0 rewrites
The application kept shipping throughout
3 layers
Query, cache and event path
Where it landed

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

C#.NET CoreUmbracoTypeScriptSQL ServerRedisAzure Service BusSignalRAzureSass