DEV Community

Akshat Jain
Akshat Jain

Posted on • Originally published at akshatjme.Medium

Why Your Database Becomes the Bottleneck

Why most backend performance issues eventually lead back to the database

In Part 1, we saw how systems collapse under pressure.

In Part 2, we saw how caching can help or hurt.

Now we look at the most common bottleneck in backend systems:

The database.

Almost every request touches it.

So when it slows down, everything slows down.

Every request depends on the database

Most backend operations rely on the database.

  • fetching data
  • storing updates
  • validating state

This makes it a central dependency.

If the database is slow, your entire system feels slow.

There is no easy fallback.

Connection pool exhaustion

Databases support limited connections.

Under high traffic:

  • all connections get used
  • new requests wait in queue
  • latency increases

This happens even before the query runs.

If the wait time grows, requests start failing.

Slow queries under load

Queries that look fast at low traffic become slow at scale.

Because now:

  • many queries run together
  • resources are shared
  • contention increases

Even a small delay per query becomes a big problem when multiplied across thousands of requests.

Lack of proper indexing

Without indexes, the database scans large data to find results.

At small scale, it may work.

At large scale, it becomes expensive.

This increases:

  • response time
  • CPU usage
  • overall system load

Indexes are one of the simplest and most ignored optimizations.

N plus 1 query problem

Instead of one efficient query, the system makes many small queries.

Example:

  • fetch list
  • then fetch details one by one

This increases:

  • number of DB calls
  • total latency
  • load on database

At scale, this becomes a major bottleneck.

Write heavy operations

Writes are more expensive than reads.

Frequent writes can:

  • lock rows
  • block reads
  • increase contention

When reads and writes happen together, they slow each other down.

No read write separation

Using a single database for everything creates pressure.

Reads and writes compete for the same resources.

A better approach:

  • primary database for writes
  • replicas for reads

Without this, scaling becomes harder.

Inefficient data modeling

Poor schema design creates long-term problems.

  • too many joins
  • deeply nested relations
  • unnecessary complexity

This makes queries slower and harder to optimize.

Good design reduces work before optimization is even needed.

Unbounded queries

Queries without limits can become dangerous.

  • fetching too much data
  • no pagination
  • large scans

These queries consume more memory and take longer to execute.

Under load, they affect other queries as well.

Locking and contention

When multiple operations try to access the same data, locks are created.

Too many locks lead to:

  • waiting queries
  • slower execution
  • reduced throughput

This is common in write-heavy systems.

Database scaling limits

Databases have limits.

Vertical scaling can only go so far:

  • CPU limits
  • memory limits
  • cost increases

Beyond a point, adding more power does not help.

You need better design, not just bigger machines.

Conclusion

It has limited resources and handles critical operations.

As load increases, small inefficiencies become visible.

Most performance issues are not sudden.

They build slowly and show up when the system is under pressure.

Understanding these patterns helps in avoiding common mistakes.

In the next part, we will look at rate limiting and how controlling traffic can prevent overload.

Thanks for reading.

Top comments (0)