advanced 3 min answer Multiple choice

A crawling fleet opens about 12000 short-lived outbound HTTPS connections per second through a single NAT device and each closed connection is held in a time-wait state for roughly 120 seconds. Which estimate and which binding ceiling are right?

natconntrackephemeral portsestimationport exhaustion
Pick one
Show the full answer Hide the answer

The assumptions, stated

12,000 new connections per second. Each tracked entry lives for the connection's duration plus a time-wait hold of about 120 seconds, which dominates for short connections. Translation is to a small set of public source addresses.

The arithmetic, step by step

Table size. In steady state, entries = arrival rate × lifetime:

12,000 /s × 120 s = 1,440,000 entries

At roughly 300 bytes per entry that is about 430 MB of tracking state - large, and well within what a sized device can hold. Many Linux builds ship a default connection-tracking maximum in the low hundreds of thousands, so the default is exceeded by a factor of about 5 and must be raised deliberately; a managed NAT service has its own published per-gateway ceiling instead.

Port range. A translated flow is identified by the tuple (public source address, source port, destination address, destination port). For one public address talking to one destination address and port, the distinct identities available are the usable ephemeral ports - roughly 28,000 to 64,000 depending on configuration. With a 120-second hold, each port can be recycled only every 120 seconds:

28,000 ports / 120 s ≈ 233 new connections per second, per destination, per public address

To sustain 12,000 connections per second towards a single destination, you need about 12,000 / 233 ≈ 52 public source addresses. If the traffic is spread across thousands of destinations, the same ports are reused against different destinations and the ceiling effectively disappears.

The number, with its range

1.4 million entries, and a hard requirement of roughly 50 or more public source addresses if the crawl concentrates on a handful of hosts. One address supports about 230 connections per second to one destination - a figure worth memorising, because it is the one that surprises people.

Which assumption dominates the error

Destination diversity. It swings the port ceiling by two orders of magnitude and nothing else in the estimate comes close. The second-largest is the time-wait hold: halving it to 60 seconds halves the table and doubles the per-address connection rate.

Why the other options fail

  • 14,000 entries forgets that closed connections are still tracked; it multiplies the rate by about one second instead of the hold time. CPU is rarely the first wall on a modern path.
  • 1.4 million with the table as the binding ceiling gets the arithmetic right and the diagnosis wrong. The table is a number you can raise with a configuration change or a larger gateway; the port range is set by the protocol and can only be worked around with more addresses.
  • 86 million entries multiplies by two hours instead of two minutes. Bandwidth is not close: 12,000 small connections per second is a few hundred Mbps.

What the number rules in or out

When this is the wrong estimate to make

For a workload with few long-lived connections - a mesh of persistent gRPC channels, a pooled database fleet - the entry count is small and stable, and the interesting ceilings are memory per connection and file descriptors instead. It is also the wrong model where egress is mostly to the cloud provider's own services: do the private-endpoint work first rather than sizing a table, because the right answer is to stop generating the state rather than to hold more of it.

What the number rules in or out, in practice

It rules out "add another NAT gateway" as a reflex - more gateways help only if traffic is distributed across them with distinct address pools. It rules in three concrete moves: reuse connections instead of creating them (the single biggest win, since a pooled client at 1,000 concurrent connections needs 1,000 entries rather than 1.4 million), shorten the time-wait hold where the protocol allows, and route object-storage and other in-cloud traffic through private endpoints so it never consumes translation state at all.