Skip to main content

Connector Tuning

Overview​

The Connector reads its sizing and concurrency settings from environment variables on its ECS task definition. Most of them are set through properties on the frontend block of the Environment construct.

Two rules apply to every property on this page:

  • There are no CDK-side defaults. Omitting a property omits the variable entirely, and the Connector applies its own default. The defaults listed below are the Connector's.
  • A misspelt variable name fails silently. The Connector resolves an unknown name to its default and starts normally, so a task definition can look configured while nothing changed. Set these through the CDK properties rather than by hand.

These settings also reach Fargate executor services, which share the Connector's container configuration.

Configuration​

import { Environment } from "@stage-tech/depot-cdk";

new Environment(stack, "MyEnvironment", {
account: { name: "example", id: Aws.ACCOUNT_ID },
name: "example",
frontend: {
auroraPool: {
maximumPoolSize: 30,
minimumIdle: 5,
connectionTimeoutMillis: 45000,
},
threadPools: {
dbPoolQueueCapacity: 500,
},
},
});

Every Connector tunable​

Where the CDK property column says none, the variable is readable by the Connector but cannot be set from an environment declaration.

Aurora connection pool​

frontend.auroraPool.*. Every duration is in milliseconds.

Environment variableCDK propertyDefaultControls
DEPOT_AURORA_POOL_MAXIMUM_POOL_SIZEauroraPool.maximumPoolSize10HikariCP maximum pool size
DEPOT_AURORA_POOL_MINIMUM_IDLEauroraPool.minimumIdle3idle connections kept open
DEPOT_AURORA_POOL_CONNECTION_TIMEOUTauroraPool.connectionTimeoutMillis30000wait for a connection before failing
DEPOT_AURORA_POOL_IDLE_TIMEOUTauroraPool.idleTimeoutMillis60000idle connection retirement — inert at the default maxLifetime, see below
DEPOT_AURORA_POOL_MAX_LIFETIMEauroraPool.maxLifetimeMillis30000maximum connection lifetime
DEPOT_AURORA_POOL_VALIDATION_TIMEOUTauroraPool.validationTimeoutMillis5000connection validation timeout
DEPOT_AURORA_POOL_LEAK_DETECTION_THRESHOLDauroraPool.leakDetectionThresholdMillis120000log a warning for a connection held this long

frontend.auroraPoolMaximumPoolSize is the older flat form of auroraPool.maximumPoolSize. It still works, but setting both throws at synth time — they map to the same variable.

DEPOT_AURORA_POOL_TEST_CONNECTION_COUNT exists too and is deliberately not exposed. It sizes the test-harness pool factory and has no meaning in a deployed environment; depot-local sets it directly.

HikariCP overrides two of these silently​

HikariConfig.validateNumerics rewrites values it considers inconsistent, warns to the log, and carries on. Two of the defaults above sit on those rules.

idleTimeout is disabled whenever it is within a second of maxLifetime. At the defaults — idleTimeout 60000 against maxLifetime 30000 — that condition holds, so idle connections are not retired on their own schedule at all; they simply reach their maximum lifetime. Lower idleTimeoutMillis below maxLifetimeMillis if you want idle retirement, or raise maxLifetimeMillis.

maxLifetime below 30000 is replaced by 1800000, thirty minutes. The default is exactly 30000, so any reduction crosses that cliff and lands 60× higher than intended rather than lower.

Both rewrites are logged as warnings at pool construction and are otherwise invisible.

Pool size applies per pool​

The Connector creates one Aurora pool per distinct connection identity and applies maximumPoolSize to each. Four distinct Aurora connections at maximumPoolSize: 30 open up to 120 connections, not 30. Size against the database's connection ceiling divided by the number of pools.

Test and run defaults differ​

Five of the seven settings above have different defaults in test mode and run mode. The Connector selects between them by inspecting the connection string and username rather than from an explicit setting, and that inference can select test defaults in a deployed environment. The table lists run-mode defaults. An explicitly set property is not subject to the inference.

Thread pools​

frontend.threadPools.*.

Environment variableCDK propertyDefaultControls
DEPOT_WORKER_THREADSthreadPools.depotWorker.threads0depot-worker pool size
DEPOT_WORKER_QUEUE_CAPACITYthreadPools.depotWorker.queueCapacity1000depot-worker queue depth, and the basis of its alarm
DEPOT_SYNC_IO_THREADSthreadPools.syncIo.threads8depot-syncio pool size
DEPOT_SYNC_IO_QUEUE_CAPACITYthreadPools.syncIo.queueCapacity1000depot-syncio queue depth
DEPOT_DB_POOL_QUEUE_CAPACITYthreadPools.dbPoolQueueCapacity0queue depth shared by the depot-dbfetch and depot-dbconn pools

DEPOT_WORKER_THREADS of 0 means derive from the CPU count​

Zero is not "no threads": it selects twice the available processor count, which is the value a literal cannot express because it depends on the task size. Omitting the property and setting it to 0 are equivalent. Any positive value wins.

dbPoolQueueCapacity of 0 means no queue​

Not a queue of length zero: both JDBC pools get a SynchronousQueue and reject work as soon as every thread is busy. Their queue.size metrics therefore read 0 whatever the load, and the /echo saturation gate cannot fire for them. Set a positive value to give them a real queue and make those metrics meaningful.

Those two pools are sized from DEPOT_AURORA_POOL_MAXIMUM_POOL_SIZE and SNOWFLAKE_MAX_CONCURRENCY together, at (aurora + snowflake) × 1.1. At the default of 256, Snowflake dominates.

Raise the thread count, not the queue​

A queue absorbs a cold start, where several datasets resolve at once. A queue that is persistently deep rather than spiky means the pool behind it is too small; deepening it only lengthens the wait. This applies to depot-syncio in particular, whose sizing is unmeasured against real admin traffic.

depot-syncio also drains to zero threads when idle, so a pool size of 0 is healthy rather than a missing metric.

Query and client limits​

Environment variableCDK propertyDefaultControls
SNOWFLAKE_MAX_CONCURRENCYsnowflakeMaxConcurrency256Snowflake client maximum concurrency
GRAPHQL_MAX_QUERY_CHARACTERSgraphql.maxQueryCharacterssee GraphQL Query Limits
GRAPHQL_MAX_QUERY_TOKENSgraphql.maxQueryTokenssee GraphQL Query Limits
GRAPHQL_MAX_WHITESPACE_TOKENSgraphql.maxWhitespaceTokenssee GraphQL Query Limits
GRAPHQL_MAX_RULE_DEPTHgraphql.maxRuleDepthsee GraphQL Query Limits
GRAPHQL_MAX_QUERY_COMPLEXITYgraphql.maxQueryComplexitysee GraphQL Query Limits
GRAPHQL_MAX_QUERY_DEPTHgraphql.maxQueryDepthsee GraphQL Query Limits
STAGE_LOG_MIN_SEVERITYlogLevel—Connector log level
REDIRECTING_ENABLEDredirecting—redirect responses to work around the 30 s API Gateway cutoff

Derived from task size​

EVENTS_PRIMARY_MIN_THREADS, EVENTS_PRIMARY_MAX_THREADS, EVENTS_SECONDARY_MIN_THREADS and EVENTS_SECONDARY_MAX_THREADS size the SQS receiver pools. All four take the same value, derived from frontend.taskSize, and there is no property to override them independently. Minimum equals maximum, so the receiver pools are fixed-size.

taskSizeReceiver threads
XSMALL1
SMALL2
MEDIUM4
LARGE, XLARGE8
unset2