Performance Optimization & Scaling

I fix applications that have become slow, expensive to run, or that fall over under load — starting with measurement, not with a rewrite.

Most performance work I take on resolves to a handful of unindexed queries, an N+1 in a hot path, or synchronous work that should have been a background job. Those are days of work, not months. I will find out which it is before quoting you for anything larger.

How do you find what is actually slow?

By measuring it, before changing anything. Guessing at performance is how teams spend a quarter optimising something that was never the bottleneck.

That means query logging and execution plans on the database, request tracing through the application, and profiling under something resembling real load rather than one developer clicking around. The output is a ranked list: here is what is slow, here is why, here is what fixing each one costs and buys.

You get that list whether or not you hire me for the fixes. It is a fixed-scope engagement — typically three to five days — and it is deliberately the first thing we do.

What usually turns out to be the problem?

In roughly the order I find them:

  • Missing or wrong database indexes — cheapest fix, biggest single win, most common cause
  • N+1 query patterns from an ORM quietly issuing one query per row
  • Synchronous work in the request path — sending email, generating a PDF, calling a third-party API — that belongs in a queue
  • No caching at all, or caching in the wrong layer with no invalidation strategy
  • Unbounded queries that were fine at ten thousand rows and are not at ten million
  • Frontend shipping far more JavaScript than the page needs

Do we need to rewrite or move to microservices?

Almost certainly not, and I will try quite hard to talk you out of it.

A rewrite means paying to rebuild everything you already have, for a year, while shipping nothing your customers can see — and arriving at a new system with new bugs. Microservices add network calls, partial failure and deployment complexity to solve a problem most single-team products do not have.

I have done both when they were warranted, including splitting a monolith into services with gRPC where the workloads genuinely diverged. But that is the answer maybe one time in five, and it should follow evidence rather than precede it.

How do we know it worked?

Numbers from before and after, on the same measurement, in production. Not a claim that it feels faster.

Each engagement ends with a written comparison — the metrics we agreed to move, what they were, what they are now, and what I did not fix and why. If something turned out not to be worth the cost of fixing, that goes in the document too.

I also leave monitoring in place, so the next regression shows up on a dashboard rather than in a customer complaint.

What you get

  • Written performance audit with a ranked, costed list of bottlenecks
  • Before and after measurements on the agreed metrics
  • Database indexes and query rewrites
  • Caching layer with a documented invalidation strategy
  • Background job queue for work moved out of the request path
  • Monitoring and alerting so the next regression is visible
  • A note on what I deliberately did not fix, and why

Tools I use for this

PostgreSQLMongoDBRedisBullMQNode.jsNestJSPythonFastAPIElasticsearchDockerKubernetesAWSNext.jsgRPC

A good fit if

  • An app that was fine at launch and has degraded as data grew
  • A cloud bill rising faster than usage, with no clear explanation
  • A product falling over at predictable peaks
  • A team that has been told it needs a rewrite and wants a second opinion first
  • Slow pages hurting conversion or search ranking

Not a fit if

  • Tuning a database you will not give me production-like data or query logs for — I cannot fix what I cannot measure
  • Optimising a system nobody is allowed to change, where only the symptom may be treated
  • Kernel, network or bare-metal infrastructure tuning; that is a systems engineer's job
  • Situations where the real constraint is the team's process rather than the code, though I will tell you if that is what I find

Work that shows this

Questions clients ask

How much faster can you make it?

Unknowable until I measure, and anyone quoting you a percentage before looking is guessing. What I can say is that where the cause is a missing index or an N+1 — which is common — the improvement tends to be an order of magnitude rather than a few percent, for a few days of work. The audit tells us which case you are in before you commit to anything larger.

Will you need production access?

I need production-like data volumes and real query logs, which is not the same as production credentials. A restored anonymised snapshot in a staging environment is usually enough and is what I prefer. Where read-only production access is genuinely necessary I will say so and explain why.

Can you do this without breaking things?

Index additions and query rewrites are low-risk and reversible, and go out first. Anything structural — caching, queue migration, schema changes — ships behind a feature flag or in a reversible migration, with the rollback tested before deployment rather than improvised during an incident.

Do you fix frontend performance too?

Yes — bundle size, render blocking, image handling, Core Web Vitals, and the rendering strategy on Next.js applications. In practice I measure both ends first, because teams often assume the frontend when the server response time is the actual problem, and occasionally the reverse.

Need performance & scaling?

Tell me what you're building and what's in your way. I reply within 24 hours with honest questions and a rough estimate — no sales sequence.