Skip to main content

Work out how many database connections an instance actually allows, using each provider's own published rule.

Provider
Engine
4 vCPU · 32 GiB
db.r7g.xlarge
Default max connections
3,324
The formula alone gives 3,604RDS reserves memory for the OS and its own processes, so the real figure is lower.

The same memory on each provider32 GiB, PostgreSQL

AWS RDS
3,324
Google Cloud SQL
600
Azure Flexible Server
3,437

The published rule

LEAST({DBInstanceClassMemory/9531392}, 5000)

How many connections a managed database will actually give you

Every managed database has a connection ceiling, and none of the three big clouds sets it the same way. AWS derives it from a formula over instance memory, Azure publishes a fixed table per product, and Google Cloud SQL uses memory tiers that jump in steps. This tool applies each provider's own published rule so you can see the real ceiling before you design a pool around a guess.

How it works

  • Applies the provider's documented rule to the instance you pick, rather than a rule of thumb.
  • Shows the AWS formula result and the realistic result side by side, because DBInstanceClassMemory is smaller than the instance's RAM.
  • Compares all three clouds at the same memory, which is where the differences become impossible to ignore.
  • Subtracts the connections Azure reserves for replication and monitoring, so the figure shown is the one your application can use.
AWS RDS, from the documented default parameters
  PostgreSQL   LEAST({DBInstanceClassMemory/9531392}, 5000)
  MySQL        {DBInstanceClassMemory/12582880}
  MariaDB 10.5+ LEAST({DBInstanceClassMemory/25165760}, 12000)

Azure Flexible Server
  a published table per product, roughly 107 per GiB, capped at 5000
  minus 15 reserved for replication and monitoring

Google Cloud SQL
  published memory bands, lower bound inclusive
  3.75-6 GiB -> 100   6-7.5 -> 200    7.5-15 -> 400
  15-30      -> 500  30-60  -> 600   60-120 -> 800
  120+       -> 1000

Worked example

A db.r7g.xlarge running PostgreSQL — 4 vCPU and 32 GiB of memory — and what the same 32 GiB buys elsewhere.

  1. 32 GiB = 34,359,738,368 bytes
  2. 34,359,738,368 / 9,531,392 = 3,604 — the formula's answer
  3. the 5,000 cap does not bind at this size, so 3,604 stands
  4. but DBInstanceClassMemory is not the instance's RAM: RDS subtracts the OS and its own processes first
  5. applying the overhead AWS documents gives roughly 3,324 in practice
  6. Azure at 32 GiB: 3,437 total, 3,422 usable after the 15 reserved
  7. Google Cloud SQL at 32 GiB: 600, because 32 falls in the 30-to-60 GiB band

Identical hardware, and Cloud SQL gives you a fifth of what the other two give you. If you are moving a service between clouds, this single number is more likely to break the migration than anything in your schema.

Reading the result

  • DBInstanceClassMemory is not the memory on the instance sticker. RDS reserves memory for the operating system and its own management processes and computes the formula over what is left. AWS documents the gap with a worked example: an 8 GiB instance yields about 630 connections where the naive division gives 683. That is roughly an 8% shortfall, and it applies at every size.
  • Google Cloud SQL uses published bands rather than a formula, so the limit does not rise smoothly with memory — inside a band it does not rise at all. Every instance from 30 GiB up to just under 60 GiB gets the same 600 connections, so doubling memory within a band buys nothing, and the entire increase lands at the boundary.
  • Azure's B1ms is special-cased at 50 connections and does not follow the otherwise consistent per-GiB pattern. That is why this tool reproduces Azure's table literally instead of fitting a line through it.
  • These are defaults, not hard limits. max_connections is a modifiable parameter on all three clouds. Raising it is usually the wrong fix, because each connection costs memory and a backend process — the reason the default tracks memory in the first place.
  • A connection limit is not a concurrency target. Postgres does not get faster as connections rise; past roughly a few times the core count, more connections mean more context switching and less throughput. Use a pooler and keep the pool well below the ceiling.

Common questions

Why does my instance report a different max_connections than this?
Three common reasons. The parameter group may have been modified, in which case your value overrides the formula entirely. The engine version matters — MariaDB changed its divisor at 10.5. And on AWS the figure moves slightly with the exact memory the host reports, which is why this tool shows both the formula result and the realistic one.
Should I just raise max_connections?
Usually not. Each PostgreSQL connection is a backend process with its own memory, and each MySQL connection carries per-thread buffers. Raising the ceiling moves the failure from refused connections, which are visible and recoverable, to memory pressure and the OOM killer, which are neither. A connection pooler is almost always the better answer.
Does a read replica have the same limit?
It has the limit its own instance class gives it, which is often the same because replicas usually match the primary. But replica connections are counted separately, so routing reads to a replica genuinely buys headroom on the primary rather than just moving the problem.
Why is Cloud SQL so much lower?
Google sizes the default around what the instance can serve well rather than what it can technically accept, and expects heavy-connection workloads to sit behind a pooler. The number is a design opinion, not a hardware constraint — but it is enforced, so it constrains you either way.