Back to the experiment list
E003CompletedP0

Connection count, connection surges, and pooling

What burden do authentication, connection renewal, and surge handling impose on DSQL?

Results summary

This experiment checked how much of a burden IAM authentication and connection setup impose when an application connects to DSQL, and whether rejections or delays occur when connections arrive all at once. As a minimum scope (MVP), we measured token signing, sequential connections, persistent connections compared with a new connection per request, and simultaneous requests for 500 and 1,000 connections, from one load generator against one DSQL cluster holding E002-scale data. No controls were measured this time.

DSQL authenticates with a token signed through IAM instead of a password. Token signing happens inside the runner without a network call and took p50 0.2 ms; only the first call took 131 ms because of client initialization. Opening a new connection and completing the first query took p50 15.5 ms, p95 109 ms, and p99 120 ms over 100 sequential runs.

Sixteen workers with persistent connections handled 8,370 product lookups per second (p50 1.9 ms), but when they opened a new connection per request this fell to 121 per second (p50 131 ms), about one seventieth. When 500 and 1,000 connections were requested at once, all succeeded without rejection, but establishing all of them took 3.7 seconds and 8.2 seconds respectively. This rate (about 120–135 connections per second) is similar to the throughput with a new connection per request, so this measurement could not distinguish whether it is a DSQL limit on the connection establishment rate or the limit of the runner’s single Python process in handling TLS connections. New connections right after the surge took p50 16.2 ms, the same as usual.

Production readiness

DSQL’s IAM token authentication itself imposed little burden. Signing took 0.2 ms, and reusing a token for several minutes removes the need to sign for every connection. Requesting 1,000 connections at once produced no rejections. However, each new connection took 15–120 ms, so a design that opens a new connection for every request (for example, short-lived functions that run without a connection pool) dropped to about 1/70 of the throughput with persistent connections. Use a connection pool, and because DSQL closes connections older than one hour, configure the pool to replace connections periodically. Controls and RDS Proxy were not compared.

Question

What burden do authentication, connection renewal, and surge handling impose on DSQL?

Test conditions

  • Region and time: Seoul (ap-northeast-2), 2026-09-29 10:25–10:27 UTC.
  • Configuration: D1 Aurora DSQL single-Region cluster (public endpoint) with E002-scale data (11 million order rows and more, about 5 GiB). This is the same cluster as the second E002 measurement.
  • Client: one m7g.4xlarge Spot runner, Python 3.11, psycopg 3, TLS sslmode=verify-full. Tokens were signed with generate_db_connect_admin_auth_token.
  • Measurements:
    • 50 token signings.
    • 100 sequential connections: new connection → SELECT 1 → close.
    • 16 workers doing product lookups for 30 seconds: persistent connections versus a new connection per request.
    • Simultaneous requests for 500 and 1,000 connections (single asynchronous process).
    • 20 sequential connections right after the surge.
  • Deviations from the plan: the combinations of application concurrency 16/64/256/1,024 and pool size 16/64/128, 60 seconds of 10x connection attempts, RDS Proxy, comparison with the controls (R1, A1, A2), and memory and rejection-rate measurements were not run.

Performance results

Measurement Result
Token signing p50 0.2 ms, p95 0.3 ms, max 131.5 ms (first call)
Sequential new connection + first query p50 15.5 ms, p95 109.0 ms, p99 119.7 ms, 0 errors
Lookups, persistent connections (16) 8,370 TPS, p50 1.9 ms, p99 2.4 ms
Lookups, new connection per request (16) 121 TPS, p50 130.9 ms, p99 247.1 ms
500 concurrent connections 500 succeeded, 3.7 seconds, p50 3.6 seconds per connection
1,000 concurrent connections 1,000 succeeded, 8.2 seconds, p50 3.9 seconds and p99 8.2 seconds per connection
New connections right after the surge p50 16.2 ms, p95 24.6 ms

Development and operations

  • Authentication: connections use IAM role permissions (dsql:DbConnectAdmin) without storing a password. There is no secret rotation work, but every place that opens a connection needs token-signing code.
  • Concurrent signing problem: in E002, when 256 connections connected for the first time at the same moment, every thread looked up the instance credentials to sign a token and failed (NoCredentialsError). We fixed this by adding a lock so that signing happens only once per process, plus retries. Care is needed in code where connections pile up, such as connection pool initialization.
  • Connection lifetime: DSQL closes connections older than one hour. In E002 we replaced connections every 50 minutes.
  • Misleading diagnostic value: in E004, SHOW max_connections returned 20, but the official quota is 10,000 connections per cluster. This time, all 1,000 concurrent connections succeeded.

Cost

As part of the second E002 measurement, which used the same cluster, DSQL usage during this test window (10:26–10:28 UTC) was 2,603 DPU (about $0.03). Cluster and runner costs are included in the cost section of the E002 report.

Conclusions and limitations

  • IAM token authentication and connection surges were not a major burden on DSQL; the largest performance risk was a design that opens a new connection for every request.
  • Limitations: this was a single run, measured from a single process on one runner. We could not tell whether the connection rate during the surge was a client limit or a service limit. Without a comparison against the controls and RDS Proxy, we cannot say “how many times” faster or slower.

Cleanup record

  • This test used the cluster and runner from the second E002 measurement run (e002-20260929t081139z-4dce). The resources were deleted at 11:08–11:10 UTC, and we completed remaining_count=0 from e002.py verify (11:10:30 UTC) and a manual cross-check (0 DSQL clusters, experiment VPCs, experiment IAM roles, and open Spot requests).