Skip to main content
unbound mongodb at scale

Concurrency Tickets: Thread Starvation Under Load

2 min read Chapter 40 of 72

Concurrency Tickets

WiredTiger uses a ticket-based system to limit the number of concurrent operations accessing the storage engine simultaneously. Each read operation acquires a read ticket. Each write operation acquires a write ticket. When all tickets are in use, operations queue until a ticket becomes available.

The default ticket counts (MongoDB 7.0):

  • Read tickets: 128
  • Write tickets: 128

These defaults limit WiredTiger to 128 concurrent reads and 128 concurrent writes. This is not a bug. It is intentional throttling to prevent WiredTiger from being overwhelmed by too many concurrent operations, which would cause excessive lock contention, cache thrashing, and context switching.

WiredTiger concurrency tickets: read pool (128 tickets) and write pool (128 tickets). Application threads acquire tickets before storage engine access. When exhausted, threads wait in queue. Shows how long-running operations (collection scans, large updates) hold tickets, starving short operations.

How Tickets Create Bottlenecks

The connection pool (from CH4) allows 200 connections. Each connection can submit operations. But only 128 read operations and 128 write operations can execute in WiredTiger simultaneously. If 200 connections each submit a read query, 72 queries wait for a read ticket.

The waiting is not the primary problem. The primary problem is what happens when some operations hold tickets for a long time. A collection scan on a 68 GB collection might hold a read ticket for 30 seconds. During those 30 seconds, one of the 128 read tickets is unavailable. If 10 collection scans run concurrently, 10 tickets are occupied for 30 seconds each. The remaining 118 tickets serve the 1,000 short queries arriving per second.

// Check ticket utilization
db.serverStatus().wiredTiger.concurrentTransactions
{
  "write": {
    "out": 45,            // 45 write tickets currently in use
    "available": 83,      // 83 write tickets available
    "totalTickets": 128
  },
  "read": {
    "out": 120,           // 120 read tickets in use - near exhaustion
    "available": 8,       // Only 8 read tickets available
    "totalTickets": 128
  }
}

When available drops to single digits, new operations experience queuing delays.