# Database Ticket Servers
A database ticket server is a small dedicated database used only to issue unique IDs.
## Core Idea
Use the database's auto-increment behavior as the atomic sequence generator, then use the returned value as an ID in other databases.
```mermaid
flowchart LR
App[Application] --> T[Ticket DB]
T --> ID[New 64-bit ID]
App --> DB1[(Shard 1)]
App --> DB2[(Shard 2)]
```
## Flickr Pattern
Flickr used dedicated MySQL ticket servers with one-row tables. To avoid one ticket server becoming the only authority, they split the ID space:
```text
server 1: 1, 3, 5, 7...
server 2: 2, 4, 6, 8...
```
This preserves uniqueness without cross-server replication.
## Why It Works
- database auto-increment is atomic,
- generated IDs are compact,
- operational model is familiar,
- sequence state persists through restart,
- no per-app worker-ID assignment needed.
## Tradeoffs
- network call to get an ID,
- dedicated database service to operate,
- availability depends on ticket service health,
- strict global monotonicity can be weakened when multiple ticket servers drift,
- high write throughput can pressure the ticket DB.
## Batch Allocation Variant
Instead of one ID per call, allocate ranges:
```text
server A receives IDs 100000-109999
server B receives IDs 110000-119999
```
This reduces sequencer load at the cost of wasted IDs if a server dies before using its range.
## When It Fits
| Requirement | Fit |
|---|---|
| Globally unique numeric IDs | Strong. |
| Compact database keys | Strong. |
| Strict creation order across all IDs | Only with one authority. |
| Offline ID generation | Poor. |
| Very high write throughput | Needs batching or another design. |
Ticket servers are attractive because they are simple. They use database correctness instead of a new distributed consensus system. That simplicity is valuable when ID generation is not the main scaling bottleneck.
## Failure Modes
- Ticket server outage prevents new object creation.
- ID allocation becomes a latency dependency on every write path.
- Multi-ticket setup loses strict global ordering.
- Batch allocation wastes ranges after process crashes.
- Sequence exhaustion is ignored until the type limit is near.
- Application code assumes IDs reveal exact creation time or shard.
The failure mode is different from UUIDs. UUID generation can continue during network partitions, but it has larger keys and weaker locality. Ticket servers give compact ordered IDs but introduce a service dependency.
## Operational Notes
Run ticket servers as critical infrastructure. Monitor allocation QPS, latency, error rate, sequence headroom, replication health, and disk durability. Keep the schema tiny and avoid sharing this database with product tables.
If using two servers with odd/even IDs, document which server owns which increment and offset. A misconfigured replacement can issue duplicate IDs.
For range allocation, persist the allocated high-water mark before handing the range to an application server. Never reuse an abandoned range unless the system can prove no process used it.
## Alternatives
| Alternative | Tradeoff |
|---|---|
| UUIDv4 | No central service, larger random keys. |
| ULID/KSUID | Time-sortable, still larger than integers. |
| Snowflake-style IDs | Decentralized, needs worker IDs and clock discipline. |
| Database local auto-increment | Simple, but not global across shards. |
## Decision Checklist
- Is compact numeric identity worth a network dependency?
- What happens when the ticket DB is unavailable?
- Is global monotonic order required or only uniqueness?
- How much sequence headroom remains?
- Can application servers allocate ranges safely?
- Is the ID meant to be public, guessable, or opaque?