Creating an index changes more than the table being indexed. It also changes the database catalog, and, across a busy cluster, that can trigger a wave of catalog reads.
YugabyteDB 2025.2.8.1, released on November 4, 2026, adds three improvements that help contain that wave. They build on catalog, memory, and concurrency improvements in 2025.2.8.0, released on October 23, 2026. Together, they address how much catalog work reaches the master leader, how efficiently that work completes, and how much gets repeated.
A customer recently reported much less master CPU impact during index creation after moving to 2025.2.8. Previously, they had seen spikes above 60%; after the upgrade, they described hardly any impact. That is encouraging feedback!
Why Catalog Activity Can Overload the Master Leader
YSQL needs metadata about tables, columns, indexes, roles, and other database objects. Backend catalog caches and the YB-TServer response cache help avoid repeatedly fetching that information.
The difficult case is a burst of DDL alongside new connections:
- 1. A catalog version change makes previously cached prefetch responses ineligible for the new version.
- 2. Connections across YB-TServers request fresh catalog data from the master leader.
- 3. Another DDL advances the version before those reads finish, creating demand for another version.
- 4. Multiple catalog prefetches overlap, adding CPU work and queueing at the same leader.
Large catalogs increase the work per prefetch. Cross-region round trips stretch paged reads. More YB-TServers increase the number of sources converging on the leader. Issue #34309 documents this amplification.
The Foundation: Bound Concurrent Prefetches
In 2025.2.8.0, catalog prefetch admission control limits simultaneous prefetches on the master leader. Requests beyond the limit are rejected for client retry, keeping a fleet-wide refresh from becoming an unbounded queue.
The controls are enable_ysql_catalog_prefetch_admission and master_max_concurrent_ysql_catalog_prefetches. The release notes explicitly state that admission control does not take effect until the upgrade is finalized.
The default full cap is derived from CPU count: max(8, 2 × cores). Newly starting prefetches use a lower watermark… 50% of that cap by default, controlled by master_new_ysql_catalog_prefetch_percent. Continuations can use the full cap. On an 8-core master, that means a full cap of 16 and a new-prefetch watermark of 8.
Start with the working defaults; change the controls only to investigate a specific symptom. These limits apply to catalog prefetches. They do not throttle ordinary catalog reads made by running queries.
Pace Successive Catalog Version Changes
The controls also let DDL wait for the previous prefetch wave to drain before advancing the catalog version again. This reduces overlapping fetches of successive catalog versions.
The session GUC yb_ddl_wait_for_master_prefetch_drain_ms defaults to 30000 milliseconds. This is a deadline, not a fixed 30-second delay: when the leader is keeping up, there is no load-driven wait. Under sustained load, version-bumping DDL can pay the deadline, and that time counts toward statement_timeout. The 8.0 and 8.1 implementation allows up to twice the configured interval when the leader is rejecting continuations. Setting the GUC to 0 disables this pacing wait.
What 2025.2.8.1 Adds
1. Reuse a Local Catalog Snapshot, Then Catch Up
When the master leader is busy, an eligible connection that preloads its catalog can start with a catalog version already cached on its local YB-TServer. It then applies invalidation messages to catch up during startup, before decisions such as database access checks and session settings.
This avoids another large catalog fetch. It does not eliminate every master read.
The GUC yb_enable_stale_catalog_prefetch defaults to true; its YB-TServer flag is ysql_yb_enable_stale_catalog_prefetch. Setting it to false disables this alternative startup path.
Eligibility matters: the connection must preload, a suitable cached version and applicable invalidation messages must exist, and the leader must report overload. Otherwise, startup uses the normal fetch path. This matters especially when ysql_catalog_preload_additional_tables or ysql_catalog_preload_additional_table_list expands the preload. An ordinary connection using the default relcache-init-file path may not qualify. Under light load, a near-zero local-reuse counter is expected.
2. Give In-Progress Prefetches More Room to Finish
A connection’s prefetch can contain several separately keyed requests, each potentially spanning multiple pages.
Previously, admission control recognized subsequent pages as continuations, but could treat the first read of a later request as a new prefetch. A connection could finish the expensive part, encounter rejection on a small follow-up read, and discard its prefetch state. Retrying repeated the expensive work.
The fix recognizes later requests in the same prefetch as continuations too. This reduces redundant retries while preserving admission control for new work. Continuations use the full cap rather than the lower new-prefetch watermark; they can still be rejected at the full cap or time out.
3. Share Authentication Catalog Prefetches More Broadly
New YSQL backends read shared catalogs such as pg_authid and pg_database during authentication and startup. Repeating these reads for every connection can put substantial load on the master during connection churn.
This improvement extends YB-TServer response-cache reuse to regular backends, beyond the Connection Manager authentication-backend path. Eligible connections can reuse cached catalog responses instead of each repeating those master reads.
yb_always_increment_catalog_version_on_ddl. The authentication-cache flag, ysql_enable_read_request_cache_for_connection_auth, defaults to false. Login profiles and initialization/upgrade conditions also affect eligibility. Verify the complete configuration before expecting this benefit.Related Improvements in 2025.2.8.0
The preceding release also reduces the cost of catalog refreshes and contention underneath them. These are useful context for understanding why an upgrade can improve the overall workload without one fix explaining the entire result.
| Improvement | How it helps |
|---|---|
| Byte-based preload batching #34114 | Fewer RPCs to preload large catalog tables; fewer sequential round trips. |
| Leaner catalog-cache entries #34258 | Removes redundant padding, substantially reducing memory for cached column metadata. |
| Temporary decoding memory #34259 | Reclaims temporary row-decoding allocations during preload, reducing backend memory peaks. |
| Fewer index-option lookups #34422 | Skips unnecessary per-index-column catalog lookups during index-entry rebuilding. |
| Narrower statistics invalidation #34661 | ANALYZE on one table no longer causes statistics-cache misses for unrelated tables. |
| No filesystem UUID mutex on catalog RPCs #34012 | Removes an unnecessary shared-lock dependency from master catalog RPC handling. |
| RocksDB cache contention reductions #34361, #34362, #34359 | Moves metrics work outside the mutex, removes redundant metrics, and improves mutex behavior. |
There is also a thread-pool worker wake-order improvement, #34838, controlled by thread_pool_worker_wake_order. It addresses latency under bursts of lock contention. The issue’s motivating example involves YCQL audit logging; it is a broader scheduling improvement, and should not be presented as a proven explanation for the customer’s index-creation result.
What to Check on Your Cluster
Start by recording the installed build and the relevant YSQL settings:
SELECT version();
SELECT name, setting, source
FROM pg_settings
WHERE name IN (
'yb_enable_stale_catalog_prefetch',
'yb_ddl_wait_for_master_prefetch_drain_ms',
'yb_enable_invalidation_messages',
'yb_always_increment_catalog_version_on_ddl'
)
ORDER BY name;
This inspects the connected backend. Check YB-TServer flags through your deployment tooling as well, including the authentication-cache prerequisites.
Verify admission control on the master leader using its web endpoint (default port 7000):
curl -s 'http://:7000/varz?raw' |
grep -E 'enable_ysql_catalog_prefetch_admission|master_max_concurrent_ysql_catalog_prefetches|master_new_ysql_catalog_prefetch_percent'
Adjust the endpoint and access options for your deployment. Confirm enable_ysql_catalog_prefetch_admission=true after finalization. A TServer’s /varz can show an inert copy of this flag as false; that value does not govern master admission.
curl and /varz?raw on masters and TServers. For catalog prefetch admission, check the master leader.For a useful before/after comparison, replay the same DDL sequence against the same schema while maintaining a fixed rate of new connections across the same YB-TServers. Keep hardware, region placement, pooling, and cache warm-up conditions comparable. Measure:
- ● Master-leader CPU and catalog-read RPC latency.
- ● Connection-establishment latency, especially p95 and p99.
- ● Catalog prefetch admissions and retries.
- ● YSQL backend memory during startup and refresh.
Use these exported metric names:
| Metric | Endpoint (default port) | Interpretation |
|---|---|---|
ysql_catalog_prefetches_in_progress | Master leader, :7000/metrics | Gauge: prefetches currently being served; compare with the effective cap. |
ysql_catalog_prefetch_rejections | Master leader, :7000/metrics | Counter: rejected prefetch reads. Rising counts can indicate admission control is protecting capacity. |
ysql_catalog_prefetch_new_admissions | Master leader, :7000/metrics | Counter: reads admitted as newly starting, rather than continuing. |
yb_ysqlserver_StaleCatalogPrefetch_count | Each TServer, :13000/metrics | Counter: connection starts using local catalog reuse. Execute a query so the backend reports its counter. |
Read the counters together. Rejections and local reuse rising together can indicate that the leader is shedding work while eligible connections avoid another full fetch. If rejections rise but local reuse stays flat, check the GUC, preload configuration, cached-version availability, and invalidation-message eligibility. Near-zero rejections can simply mean the workload never reaches the watermark.
For memory investigations, enable --vmodule=pg_response_cache=1 on the affected TServer. Its fill-completion log reports how many waiters receive a cached page together. Those backends can expand catalog data simultaneously, causing a memory spike. Each log line describes one page: serialized page bytes multiplied by waiters is not an estimate of backend memory usage.
The Practical Tip
Should you upgrade? If you are running an older 2025.2 release and see master CPU spikes or slow connections during DDL, these improvements make a strong case for prioritizing an upgrade. Large catalogs, frequent schema changes, heavy connection churn, and deployments spanning regions make the changes especially relevant.
Between 2025.2.8.0 and 2025.2.8.1, I would evaluate 2025.2.8.1 as the upgrade target. It builds on the 8.0 improvements and adds the catalog-reuse, continuation, and authentication-prefetch enhancements described above. If you already run 8.0 and still see this pattern, the 8.1 changes are worth testing against that workload.
For a cluster with a small catalog, stable pooled connections, and little DDL activity, the immediate performance difference may be modest. These fixes strengthen the case for routine patching, but they do not, on their own, make every healthy cluster an emergency upgrade.
Before production rollout, replay a representative workload in staging and compare master-leader CPU, connection latency, and backend memory. Confirm the configuration prerequisites, and finalize the upgrade after validation so admission control can take effect. Keep connection pooling and measured DDL rollout practices in place.
Is it worth it? For workloads affected by catalog pressure, yes, there are concrete improvements targeting that bottleneck. Treat the customer feedback as encouragement to test, and use your own measurements to establish the benefit. For a new upgrade plan, also check whether a newer supported maintenance release includes these fixes.
👏 Kudos to the YugabyteDB Engineering Team!
A big thank-you to the YugabyteDB engineering team for tackling this performance bottleneck from so many angles. Reducing redundant catalog reads, avoiding repeated work, and easing contention takes careful engineering… and it addresses the operational challenges that show up as clusters grow.
For workloads hit by catalog pressure, these improvements can be a game changer: less pressure on the master leader and more responsive connections during schema changes. Great work, team! 🚀
Have Fun!
A little new-house comedy… 😂
We had the house painted and recarpeted before moving in, but one room had a Murphy bed that needed to come out so we could finish the wall behind it.
After moving in and removing the bed, I was ready to paint using the extra paint the painter said he’d left for us. Opened the bucket and found… garbage. No paint. Just his cleanup leftovers. 🤦♂️
Immediately thought of Seinfeld’s Soup Nazi, except this time…
“NO PAINT FOR YOU!” 🎨😂
