Architecture

Find a scaling bottleneck before splitting the application

Kamruz
Kamruz
Oct 14, 2026
5 min read
Find a scaling bottleneck before splitting the application

A slow application often receives an architectural diagnosis before it receives a performance diagnosis. The proposed fix is to split the application into services, even though the expensive work may be one unindexed query, an oversized response, or a report competing with interactive requests. A process boundary can isolate resources, but it cannot make inefficient work disappear. The first task is to identify what limits useful throughput and how that limit affects users.

Use an illustrative support dashboard with a fast login page and a slow case list during report generation. The example does not assume a particular traffic volume or benchmark. It shows how to establish whether the problem belongs to database access, application work, resource scheduling, or deployment independence.

Define the workload and objective

Write the user action that feels slow and the objective it must meet. A case list and a monthly export can have different latency expectations. Separate first-load behavior, repeated navigation, and large-account behavior. Record which dataset sizes and concurrency levels are representative, using synthetic data where possible.

A single average latency is insufficient. Observe latency distribution, error rate, and throughput over a bounded workload. Note whether the test uses warm caches and existing connections. A benchmark that bypasses authentication or uses a tiny account may not represent the reported journey. Keep the experiment reproducible enough that a smaller fix and a service split can be compared under the same conditions, without claiming that a local result predicts production exactly.

Follow the request's time budget

Break the request into authentication, data access, computation, provider calls, serialization, and transport. Correlate these stages with a request identifier or trace. If the database consumes most of the time, inspect queries and plans before reorganizing application modules. If serialization is expensive, examine record count and returned fields.

Look for work hidden inside loops. A list endpoint may execute a permission or relationship query for every row. A report may repeatedly load the same reference data. Count operations as well as duration. Where time is missing from instrumentation, mark the gap instead of assigning it to a fashionable cause. A plausible architecture story is weaker evidence than an observed expensive stage with a reproduction path.

Check saturation and contention

Compare slow periods with CPU, memory, database connection usage, disk activity, and queue delay. High latency with low CPU may indicate waiting on a provider or connection pool. High CPU during report generation may suggest contention with interactive work. Memory pressure may cause instability even when average latency looks acceptable.

Use resource measurements to choose the next experiment. Reducing report concurrency may improve the case list if both compete for a shared pool. Adding application replicas may worsen the problem if they create more database connections against an already saturated database. Record these dependencies explicitly. Scaling one tier is safe only when downstream capacity and connection behavior have been considered, especially when every replica starts its own background workers.

Compare the smallest credible fixes

For a slow query, compare an appropriate index, narrower projection, bounded pagination, or fewer queries. For heavy reports, compare scheduling, a worker with a concurrency limit, and an isolated process. For repetitive reads, consider caching only after defining freshness and invalidation. Each option should target the measured cause.

A practical decision artifact lists hypothesis, change, predicted signal, and result. For example, limiting report concurrency predicts lower interactive connection wait while report completion becomes slower. The predicted tradeoff makes the experiment falsifiable. Do not apply several large changes together unless recovery demands it, because their combined result will not tell you which assumption was correct. Link query-driven indexing when data access is the likely bottleneck.

Test under controlled competition

Reproduce the case list with and without report activity. Keep data and request mix stable enough to attribute the difference. Observe both user latency and report completion, since protecting one workload may starve the other. Use bounded load in an isolated environment rather than casually stressing production.

Verify correctness while measuring speed. A narrower projection must not omit required permission data. Pagination must not lose or repeat records. A cache must not leak another tenant's view. Record the version, configuration, dataset shape, and limitations beside the result. If the environment lacks production-like network or storage behavior, state that. The experiment is still useful for comparing mechanisms, but it is not a license to advertise an invented capacity number.

Decide whether a service boundary helps

A service extraction is more compelling when a workload needs independent scaling, releases, runtime, ownership, or failure isolation. If reports use a fundamentally different resource profile and can operate through a stable contract, a separate deployment may help. It still needs authentication, request or event contracts, observability, capacity planning, and compatibility.

Ask whether a worker process gives the necessary isolation while keeping domain modules together. This can meet the operational need with fewer distributed boundaries. If the database remains shared and saturated, a new service may merely relocate the caller. Compare the whole path, including data ownership and consistency requirements. See modular monolith design before making service count the measure of architectural maturity.

Preserve evidence after the change

Add a small regression check or operational view for the limiting behavior. Track query count, report concurrency, or response size if those signals explain the original problem. A broad latency alarm alone may detect recurrence too late and give little diagnostic direction. Keep thresholds tied to the user objective and realistic measurement variability.

Review the system after workload changes. A fix that removes one bottleneck may expose another, which is normal. Reuse the measurement method rather than assuming the next limitation must require a larger architecture. Document the accepted cost: an index increases write and storage work, pagination changes navigation, and lower concurrency increases background delay. Performance improvements are decisions about resources and user priorities, not free benefits.

Ask AI for falsifiable hypotheses

Provide sanitized timings, resource signals, query shapes, and a concrete journey. Ask the assistant to rank hypotheses with evidence and propose the smallest experiment that would distinguish them. Require it to separate observed facts from assumptions. Do not accept invented throughput estimates or a service decomposition based only on the feature names.

Use it to inspect loops, identify missing instrumentation, and draft the experiment record. Review suggested tools and commands before using them against shared environments. If AI proposes a cache or queue, ask which measured signal should change and what correctness condition might be harmed. This keeps assistance useful for diagnosis while leaving architectural commitments dependent on actual workload evidence.

Sources

Martin Fowler's Monolith First discussion supplies context for the cost of premature distributed boundaries.

OpenTelemetry's logs documentation is a primary reference for correlated diagnostic signals. The experiment sequence above is original guidance, not a reported benchmark.

About the Author

Kamruz

Kamruz

Full Stack Developer

A passionate developer who loves creating modern web applications and sharing knowledge with the community.

More About Me

Related Articles