Design, migrate, and run scalable, highly available databases on Google Cloud across relational and NoSQL services, and track your readiness for the Professional Cloud Database Engineer exam.
Prepare and test your skills
Prepare and test your skills
Pooling modes and configuration strategies control how application connections are mapped to database sessions in Spanner. A Spanner (opens in a new tab) session provides the context for database operations against the Spanner database service and is used to execute transactions that read, write, or modify data. Each session applies to a single database, and standalone reads, writes, and queries each use one transaction internally. How sessions are pooled, multiplexed, and transported directly affects application latency and resource use.
A session pool in Spanner is a collection of available sessions that are ready to use without a new creation round trip. Creating a new session adds latency because each creation requires a round trip to the Spanner database service, so the pool returns an existing session for an operation and reclaims it for reuse afterward. Spanner sessions are intended to be long-lived, and the pool stores existing sessions, returns the appropriate type when requested, and cleans up unused sessions. This approach spreads session-creation latency across many operations rather than eliminating it entirely.
A regular Spanner session executes a single transaction at a time, so the session pool must maintain enough sessions for concurrent work. Increasing the pool is different from adding more clients because the pool reuses backend context while additional clients add new connection and session overhead. The client should therefore return each session to the pool after use so concurrent transactions can obtain a session without waiting.
A multiplexed session is a Spanner session that executes multiple transactions at a time and supports multiple concurrent requests on that single session. Requests flow from the application into the same session context, and the session carries the concurrent transactions to the Spanner database service in parallel. Because fewer distinct sessions are created and maintained, backend overhead and resource consumption are reduced. Use multiplexed sessions when high concurrency would otherwise require a very large session pool.
A gRPC channel pool is the transport layer that carries Spanner session traffic between the client library and the Spanner database service. When traffic grows, congestion on too few channels increases high tail latency at p95 and p99 even if sessions are available. Tuning the gRPC channel pool increases transport capacity so session requests flow without queuing behind each other. Optimize this pool alongside the session pool because session reuse controls session-creation latency while channel tuning controls transport congestion during high traffic.
Session performance is managed through three complementary controls:
Pool configuration for application workloads balances the number of sessions, the number of gRPC channels, and the mix of read and write sessions. The client library pool must be sized so concurrent transactions can obtain a session without waiting, while the channel pool must be sized so those sessions can send requests without congestion. The write-sessions fraction controls how much of the pool is prepared for writes versus reads, which matters because write paths have different preparation and lifecycle needs than reads.
| Pooling approach | What is shared | Performance effect |
|---|---|---|
| Session pool | Long-lived sessions across operations in one database | Spreads session-creation round-trip latency across many operations |
| Multiplexed sessions | One session across multiple concurrent transactions | Reduces backend overhead and resource consumption for concurrent work |
| gRPC channel pool | Transport channels across session traffic | Reduces p95/p99 tail latency caused by congestion during high traffic |
For Cloud SQL workloads, the same pooling principle applies at the database-connection layer. Good connection management uses connection pooling with exponential backoff, so application connections flow from the pool to the instance and retries back off instead of overwhelming the database. The pool improves resource use and helps the application stay within Cloud SQL connection limits, while small and short transactions keep pooled connections from being held too long.
Exam tip: Use a session pool to avoid a round trip for every operation, use multiplexed sessions to run concurrent transactions on one session, and tune the gRPC channel pool when p95/p99 latency rises under high traffic.
Resource optimization and connection overhead describes the tradeoff between creating new database connections for every operation and reusing a cache of persistent backend connections. Creating a connection or session requires extra work such as a handshake and round trip to the database service, which adds latency and consumes memory and CPU. Session pooling addresses this overhead by keeping ready-to-use connections alive so many application operations can share a smaller set of backend connections.
Connection handshake cost is the latency and resource use paid to create a new Spanner (opens in a new tab) session with the Spanner database service. Each Spanner session applies to a single database and is used to execute transactions that read, write, or modify data in that database. Creating a new session requires a round trip to the Spanner database service, so creating a session for every operation repeats that cost and directly increases application latency. Tuning the gRPC channel pool is specifically aimed at high tail latency, such as p95 and p99 latency, caused by channel congestion when traffic is high.
Session performance can be managed in three related ways:
A session pool is a collection of available Spanner sessions that are ready to use for database operations. Rather than creating a session for every operation, the pool returns an existing session when the application requests one and then reclaims that session for reuse afterward. The pool stores existing sessions, returns the appropriate type of session when requested, and cleans up unused sessions. Spanner sessions are intended to be long-lived, so after a session is used the client should return the session to the pool for reuse.
This reuse spreads the session-creation latency across many operations rather than eliminating it entirely. The result is fewer handshakes between the client and the Spanner database service, lower average latency, and less repeated work to establish context for each transaction. The flow is fixed: the application requests a session from the pool, the session carries the transaction to the database service, and the session returns to the pool for the next operation.
Exam tip: A session pool spreads session-creation latency across many operations; it does not eliminate the initial round trip required to create each pooled session.
A multiplexed session is a Spanner session that can execute multiple transactions at a time, while a regular session executes a single transaction at a time. Standalone reads, writes, and queries each use one transaction internally, so without multiplexing each concurrent operation needs its own session context. Multiplexed sessions let an application make multiple concurrent requests on a single session, which reduces backend overhead and resource consumption. This design optimizes system memory and CPU because fewer session objects need to be created, tracked, and maintained on the backend.
The application still sends concurrent database work, but the work flows from many application requests through one shared session to the Spanner database service. Choose multiplexed sessions when concurrent load would otherwise require a large number of individual sessions. The sharing lowers backend tracking cost without reducing the number of concurrent transactions the application can submit.
An application connection pool such as HikariCP (opens in a new tab) for Cloud SQL for PostgreSQL and MySQL controls resource use through pool size limits. The maximumPoolSize setting limits the total number of concurrent connections the pool will keep, while the minimumIdle setting is the minimum number of idle connections Hikari maintains in the pool. Additional connections will be established to meet the minimum idle value unless the pool is full, and ideal values are highly variable based on application design, infrastructure, and database.
Correct sizing connects the application tier to the database limit because total demand flows from application instances to pooled connections to the database. Calculate the maximum connections that can be established per compute instance, such as per Cloud Run instance, and configure maximum instances so that maximum instances times connections per instance is less than the maximum connections allowed by the database. This calculation prevents connection exhaustion while keeping enough reusable connections warm for efficient reuse.
Concurrency management in scalable architectures is the practice of controlling how many simultaneous requests and application instances share limited database connections. In cloud environments, compute layers such as Cloud Run (opens in a new tab) and Cloud Run functions can scale from zero to hundreds of ephemeral instances almost instantly, while the database can only support a fixed number of concurrent sessions. Without shared management, each new instance opening its own connections causes connection exhaustion, higher latency, and failed requests.
A session pool reduces latency and connection churn by reusing long-lived Spanner (opens in a new tab) sessions instead of creating and deleting them for every request. A Spanner session provides the context for database operations with the Spanner database service and is used to execute transactions that read, write, or modify data. Each Spanner session applies to a single database, and creating a new session requires a round trip to the Spanner database service, which adds latency. A session pool is a collection of available sessions that are ready to use, so the pool returns an existing session for an operation and reclaims it for reuse afterward.
Request flow therefore moves from the application to the pool, from the pool to the database service, and then back to the pool for reuse after the operation completes. Spanner sessions are intended to be long-lived, so the client should return the session to the pool instead of discarding it. This spreads session-creation latency across many operations and prevents the churn of constantly creating and deleting sessions under high concurrency.
Session performance can be managed in three related ways:
Ephemeral serverless instances require pooling because many short-lived compute instances depend on one shared database connection limit. A Cloud Run instance can serve multiple requests simultaneously, concurrently, up to a configurable maximum concurrency with a default of 80, and the platform automatically adjusts concurrency up to that maximum. When traffic spikes, Cloud Run adds instances quickly and each instance that opens its own database connections multiplies the total demand on the database.
Application database access is therefore bottlenecked by the maximum connections allowed by the database, not just by compute capacity. The total demand flows from concurrent requests to Cloud Run instances to database sessions, so operators must calculate maximum connections per Cloud Run instance and configure maximum instances so that maximum instances times connections per instance is less than the maximum connections allowed. If the application has low traffic and can tolerate higher latency, opening and closing connections per request may be acceptable, while high-traffic services need persistent pooled connections with background maintenance.
Exam tip: Keep maximum Cloud Run instances × connections per instance less than the database maximum connections to prevent exhaustion during rapid scale-out.
Multiplexed sessions and gRPC channels for high concurrency work together to carry overlapping serverless requests without requiring one dedicated session per transaction. A multiplexed session in Spanner is a session that executes multiple transactions at the same time, while standalone reads, writes, and queries each use one transaction internally. Traffic flows from multiple concurrent application requests into the single multiplexed session and then to the Spanner database service, which reduces backend overhead and resource consumption. This sharing is especially valuable when hundreds of serverless requests overlap but the database cannot afford hundreds of separate sessions.
The gRPC channel carries Spanner session traffic between the client library and the database service, and congestion on that channel appears as high tail latency at p95 and p99 during heavy load. Tuning the gRPC channel pool lets more session traffic move in parallel without blocking, so latency stays stable as concurrency grows. Together, multiplexed sessions reduce the number of sessions needed and tuned gRPC channels keep the remaining transport path from becoming the bottleneck.
Balancing request concurrency, memory, and cost means choosing a Cloud Run concurrency value that fits the container's ability to share CPU, memory, and database connections. Cloud Run concurrency controls how many requests each instance handles at once, and the correct value depends on shared resources such as variables and database connections. Lower the maximum when the container cannot safely process many concurrent requests, and increase it when the container can handle a large volume without contention. Each request also needs additional memory, so adjust the memory limit up or down together with concurrency to avoid pressure or waste.
To find the maximum stable concurrency for a service, follow an ordered test loop:
The choice of concurrency trades latency, throughput, and cost against each other:
| Setting | Latency per request | Throughput per instance | Instances needed |
|---|---|---|---|
| Lower maximum concurrency | Lower, because fewer requests compete for CPU and memory inside the instance | Lower, because each instance serves fewer requests at once | More instances to serve the same traffic |
| Higher maximum concurrency | Higher, because requests wait for CPU, memory bandwidth, and connections | Higher, because each instance processes more requests at once | Fewer instances to serve the same traffic |
Billing follows billable instance time, so a lower setting can lower cost only when faster completion and faster shutdown outweigh running more instances. The reliable way to choose is to load test different settings and compare the container billable instance time metric to find the lowest-cost point that still meets latency goals.
Last updated