A FinTech client was running a monolithic backend that shipped once a month. Releases were events — planned, rehearsed, and occasionally rolled back. Cloud spend had grown faster than usage, because capacity had been provisioned for peaks that happened rarely.
The client is under NDA, so this covers the approach and the outcomes rather than the business.
What was actually wrong
Monoliths are not a problem by themselves. Plenty of them run happily for years. This one had two specific failures:
Everything deployed together. A one-line change to a reporting query went out with everything else, which meant it waited for the next release train and carried the same risk as a change to payments. The natural response is to release less often, which makes each release bigger and riskier — a loop that tightens on itself.
Capacity was sized for the worst hour of the month. Servers were provisioned for peak load and ran at a fraction of it the rest of the time. Nothing was wrong technically, and most of the money was being spent on idle headroom.
In a regulated environment both problems get worse, because every change needs an audit trail and every environment needs to be reproducible on demand.
Assessment before architecture
We started by auditing the existing workloads and their dependencies — not to design the target state, but to find out which parts of the monolith actually needed to move and in what order. A decomposition plan that ignores the dependency graph produces microservices that cannot deploy independently, which is the worst of both worlds: distributed complexity with none of the autonomy.
We then validated the target architecture with a proof of concept against real workloads before migrating anything. The PoC exists to surface the things a design document cannot — and it did, which is cheaper to learn there than mid-migration.
How we decomposed it
Incrementally, never as a rewrite. Services were carved out one at a time, each with its own data ownership and its own deployment pipeline, while the monolith kept serving everything not yet extracted. At every point the system was fully working — there was no cutover weekend and no parallel-universe rewrite to reconcile.
Order mattered: the services extracted first were the ones that changed most often and touched the least shared state, because those deliver the deploy-frequency benefit immediately with the least risk.
The platform underneath
Docker for consistent packaging, so a service behaves the same on a developer's machine, in CI, and in production.
Terraform for all infrastructure. Every environment is described in code and rebuilt from that description — which matters commercially, since a reviewer asking "what exactly is running in production?" gets a file in version control rather than a person's memory. The audit trail is the git history.
CI/CD per service. Build, test and deploy independently, with automated checks as the gate. This is what converted monthly releases into daily ones: not the microservices themselves, but the fact that each one could go to production without coordinating with everything else.
Security as part of the architecture, not a later pass. Least-privilege IAM per service, encryption in transit and at rest, and no shared credentials between environments.
Then the part people skip
Decomposition does not reduce cost on its own — done carelessly it increases it. The savings came from the optimisation phase afterwards: right-sizing each service to its real measured usage rather than its inherited allocation, autoscaling so capacity follows demand instead of anticipating it, and applying FinOps discipline to find the resources nobody owned any more.
That is the step that turns a modernisation into a cheaper platform, and it only works once services are small enough to size individually.
Results
- 45% reduction in cloud costs.
- Deploy frequency: monthly → daily.
- 99.98% uptime.
The uptime figure and the deploy figure are connected, which surprises people. Smaller, more frequent releases fail less catastrophically: less changes at once, the blast radius is narrower, and a rollback is one service rather than the whole platform.
What we would tell the next client
Do not start with the microservices. Start with the deployment pipeline and the dependency map. Most of the value here came from independent deployability and from right-sizing afterwards — and you can get a surprising amount of both without decomposing everything.
And budget for the optimisation phase explicitly. It is the least exciting line in the plan and the one that paid for the project.
Running something similar? Tell us about your infrastructure and we'll start with an assessment.