İçeriğe geç
All Services

Backend Scaling

Scaling is not adding servers, it is finding the bottleneck. Measurement, database and query optimisation, cache layers, queues and a reversible migration.

Scaling is not adding servers; it is finding where the system is blocked, opening that point, and measuring that it opened. Adding servers sits at the end of that sequence and is usually unnecessary, because the slowness rarely comes from the machine's capacity. It comes from one query running on it, one synchronous step the user must wait through, or a cache layer that was never built. Optimisation without measurement is guesswork, and while guesswork sometimes lands, even then nobody knows why, so it cannot be repeated the next time load rises. That is why a scaling engagement starts with profiling rather than an architecture debate.

The difference between scaling, performance and resilience

Three separate jobs get confused: performance optimisation means serving the same load with fewer resources, scaling is about how response time behaves as load increases, and resilience is about the system staying up when one part fails. A page can be fast for one user and lock up under thousands of concurrent ones; the reverse happens too, with systems that are slow but stable under load. The three differ in cost, duration and remedy, so we write down which one it is before anything else. Work that skips that distinction usually applies the most expensive fix to the smallest problem. We covered the architectural side separately in our article on designing scalable and maintainable software architecture.

How we set up a scaling engagement

The six headings below cover every decision made in a scaling project. The first is diagnosis: what gets measured and which number counts as the target. The next three are the layers where the intervention happens: database, cache and queue. The fifth decides whether the architecture gets split. The sixth belongs at the start of the work rather than the end: measuring capacity.

Bottleneck diagnosis and measurement

Diagnosis is not done by looking at average response time, because an average is where slow requests hide behind the majority. What matters are the tail percentiles: the user who abandons the system experiences their own request, not your average. Endpoints are taken one at a time and each one's time is broken down between the database, waiting on an external service, and application code. Four more numbers go beside that: slow query logs, cache hit ratio, queue depth, and memory and CPU saturation. We propose no architectural change before that table exists, because it is the only source of a comparison point afterwards.

Database design and query optimisation

Under load the first thing to break is almost always the database, and the reason is usually not the machine. It is a query with no index, queries repeated inside a loop, or a listing screen whose result set grows without bound. Adding an index without reading the query plan is guesswork too: the wrong index slows writes and moves the problem elsewhere. The Anneekspres marketplace was built from scratch on Python and Django over PostgreSQL, where category filtering, search and the seller panel's stock and order management all run on the same infrastructure. In catalogue systems dominated by filtering, the cost sits in the query rather than the server: World Summer Schools collects hundreds of programmes in one searchable catalogue filtered by age, country, programme type and date.

Cache layers and invalidation

Adding a cache is easy; the hard part is deciding what must never enter it. A system showing stale data costs more than a slow one, so the lifetime of every cache entry and the event that drops it are written down in advance. Biletico is the concrete example: the platform was taken over and the interface, seating plan and payment flow rebuilt, while on the infrastructure side caching was placed with Redis on a Next.js and Node.js stack, with MongoDB on the data side. On the same platform the canvas-based seating plan can reflect real-time occupancy. On our side the scope of the cache, and what deliberately stays outside it, is settled as a written decision. Cache structures were part of the performance work on Welldone and Tegoly too.

Queues and event-driven asynchronous processing

A user request should only do the work the user is waiting for. Invoice generation, notification delivery, report calculation and calls to external services are not that work. Lifted out of the request path onto a queue, response time drops and the order flow stays up when a third-party service goes down. On the Anneekspres infrastructure the message queue was built with RabbitMQ, and the case page states that this infrastructure keeps the system running without interruption under high traffic. Lextum AI was built on a microservice architecture with asynchronous processing over RabbitMQ, ready for high-traffic enterprise use. Queues are not free: message loss, double processing and ordering are three separate conditions, each handled on its own.

Gradual migration from monolith to microservices

Microservices mean splitting an application that lives in one codebase, a monolith, into small services that talk to each other over the network; that split is a cost, not a goal in itself. Once services are separated, a function call becomes a network call, and debugging, data consistency, version compatibility and monitoring all get harder at once. Lextum AI was built with a microservice architecture, meaning it was delivered that way rather than moved off a monolith. Most systems do not need this; one application with properly separated modules is enough for a long time. When a split is genuinely required it does not happen in one go: one part whose load or release rhythm differs clearly from the rest is chosen, its boundary is written down, the read side moves first, and the write side follows only once the read side is measured as working. No second part starts in parallel.

Load testing and capacity planning

A load test is built around a real event in your business calendar rather than a round number: the minute ticket sales open, a campaign launch, the start of a season, payroll day. The target is written before the test, otherwise the result can be narrated favourably from any angle. What gets measured is not only whether the system holds, but at which point and with which symptom it breaks; without a known breaking point there is no capacity plan. For Anneekspres the requirement for a platform able to carry high traffic was set at the start. On Togodo, performance improvements delivered smooth operation under high traffic. The infrastructure built for World Summer Schools was designed to scale, ready for growing programme and user volume.

Where systems actually break

The breaking point is rarely processor power; in practice it is one of four places. First, the database: a single unindexed query fills the connection pool as load rises and leaves the whole system waiting. Second, the synchronous path: work the user is not waiting for, left in the request path, slows your system the moment an external service does. Third, a missing or badly built cache, and the second is more dangerous because it shows wrong data silently. Fourth, the release pipeline: if going live is an event, the problem you found stays live for hours or days. CI/CD automation was set up with Jenkins on Anneekspres, Biletico, Lextum AI, Welldone and World Summer Schools, and building that pipeline is a separate job handled under DevOps and CI/CD.

What scaling costs and where to stop

Every layer added is a layer that has to be operated. A cache brings invalidation bugs, a queue brings message loss and reprocessing, and splitting services brings failures arriving over the network. So two numbers go beside every scaling decision: the expected gain and the monthly operating burden of that layer. The stopping point is defined up front too. We stop when the measurement hits the target, we stop when the bottleneck is business volume rather than technology, and we do not reach for the larger fix when a cheaper one does the job. An index or one query correction is often both faster and more durable than an architectural change. Vertical growth, meaning one bigger machine, can come out cheaper than a distributed architecture, and we say so when it does. If the product is not validated yet, scaling is the wrong answer and the work belongs under MVP Development.

How the migration runs without downtime

Scaling work is done on a living system, so every step has to be reversible. The release pipeline and monitoring go in first, because a change with no rollback mechanism does not get attempted. Schema changes run in two phases: the new field is added, both shapes live side by side for a while, and the old field is removed only after it is measured as unused. Read paths move before write paths, because a mistake on the read side can be undone. Changes go out behind a flag, to a small slice of traffic first. The rollback plan is written before the change ships and names who reverts it at which threshold. On Biletico the structure that lets every update be tested and released, and on Anneekspres the pipeline that makes fast deployment possible, are the precondition for this rhythm.

Our technology selection criteria

The choice is limited to tools we run in production and that somebody else can maintain after handover. On the database side the default is relational: Anneekspres, Lextum AI and World Summer Schools use PostgreSQL, Welldone uses MySQL, Tegoly uses MSSQL, and Togodo uses both MSSQL and PostgreSQL. Where the schema is variable we move to the document side, and Biletico and Tegoly work with MongoDB. On the application side we use Node.js when the workload is I/O heavy, Python and Django when the data model and admin screens dominate, and .NET when enterprise integration and role structure decide. The cache layer runs on Redis, the queue on RabbitMQ, the servers on Ubuntu and the release pipeline on Jenkins. Three criteria decide, none of them fashion: who maintains it after handover, whether people can be hired for it, and whether hosting can stay in your own account.

Projects where this service was part of the work

Backend Scaling was part of every engagement below. The detail of each one sits on its own page in the Success Stories section.

  • Anneekspres: a marketplace for mother and child products built from scratch, with a RabbitMQ message queue, PostgreSQL for data management and Jenkins pipelines; the system runs without interruption under high traffic.
  • Lextum AI: document generation, contract review and simultaneous editing for legal teams, on a microservice architecture with asynchronous processing over RabbitMQ and a managed SaaS infrastructure on AWS.
  • Biletico: an inherited ticketing platform whose interface, canvas-based seating plan and payment flow were made functional, with Redis caching on Next.js and Node.js and MongoDB on the data side.
  • Togodo: new screens, real-time messaging and notifications added to a social events application; performance improvements delivered smooth operation under high traffic.
  • Welldone: .NET services, MySQL, cache structures and Ubuntu-based scalable server infrastructure built for an industrial laundry operation.
  • World Summer Schools: hundreds of summer school programmes gathered into one searchable catalogue, on cloud-based infrastructure over Next.js, .NET and PostgreSQL, ready for growing programme and user volume.
  • Tegoly: speed improved on a digital signature platform through cache mechanisms and optimised server configuration on Azure; the performance work brought page load times down.
  • Terazzi: optimisation work on the backend and performance side of a construction and decoration platform, which improved site performance.

Key Benefits

  • Measurement first: no architectural change proposed before a profile exists
  • Four homes for the bottleneck: query, synchronous step, cache, release pipeline
  • Query plan and index decisions before growing the server
  • Redis for cache, RabbitMQ for queues: unwaited work leaves the request path
  • Gradual, reversible migration with a written rollback plan
  • Load tests built around a real business event, not a round number

Frequently asked questions

How long does a backend scaling engagement take and how is it priced?

The work splits in two and is priced separately. First comes diagnosis: tail percentile response times, slow query logs, cache hit ratio and queue depth are extracted, ending in a ranked bottleneck list with an estimated gain for each item. Second comes implementation, and its duration depends on which items you pick from that list. We give no duration estimate before diagnosis, because it would be a guess.

Can you do this without taking the system down?

Yes. The work runs on the living system in reversible steps. Schema changes happen in two phases: the new shape is added, the old one lives alongside it for a while, and removal comes only after it has been measured as unused. Read paths move before write paths, and changes open behind a flag to a small slice of traffic. The rollback plan is written before anything ships.

What gets delivered when the work finishes?

Four things get delivered. A measurement report with before and after numbers, stating which change bought which gain. A monitoring dashboard and alert thresholds set up inside your own accounts. Load test scenarios in a form you can re-run. And an operations document: where the breaking point sits, when capacity runs out, and what to do when an alert fires. All four are handed over whether or not you continue with us.

Who handles maintenance and monitoring afterwards?

All three arrangements work: you continue with your own team, we continue, or it runs as a mix. The thresholds in the operations document drive that decision, because what to do when an alert fires is written there. If your team takes over, no separate migration is needed, since the dashboard and alerts already sit in your own accounts. Ongoing monitoring can also run as a separate service.

Does every slow system need scaling?

No, not every slow system needs scaling. If traffic is nowhere near the limit of the current server, the job is not scaling but a query or index correction. If the product is not validated yet, architecture for a system with no load is an expense. If the problem is the error rate rather than slowness, that is a resilience job, solved differently. When the diagnosis list comes out empty, we say so in writing.

Why touch the architecture instead of just buying a bigger server?

Most of the time you are right, and that is what we recommend. One bigger machine is cheaper and faster than a distributed architecture and adds no operating burden. That option ends at two points: past a certain size the price stops rising linearly, and one machine is a single point of failure. The diagnosis report puts numbers on both thresholds, so the decision is not made by guessing.

Let's Talk About Your Project

How can we apply this service to your project?

Fill out the quote form for a free 30-minute discovery call.