Putting It Together
Here is the design for each variant.
t.co
X’s servers send shorten and block requests. Browsers send follow requests. A load balancer spreads the requests across API instances. For a follow request, the API instance checks the cache first. On a miss, and for every shorten or block request, it sends the database operation through the shard router to the link’s shard. Each shard has a primary and a replica:
graph TB
X[X's Servers] -->|Shorten, block| LB[Load Balancer]
B[Browsers] -->|Follow| LB
LB --> API1[API Instance 1]
LB --> API2[API Instance 2]
API1 --> C[(Cache)]
API2 --> C
API1 --> R[Shard Router]
API2 --> R
subgraph A[Shard A]
PA[(Primary)] -.->|Replicate changes| RA[(Replica)]
end
subgraph Z[Shard B]
PB[(Primary)] -.->|Replicate changes| RB[(Replica)]
end
R --> A
R --> Z
Drive
Drive’s design is the same as t.co’s, without the cache. Drive’s servers send shorten requests and the requests to turn a link off or on:
graph TB
D[Drive's Servers] -->|Shorten, turn off| LB[Load Balancer]
B[Browsers] -->|Follow| LB
LB --> API1[API Instance 1]
LB --> API2[API Instance 2]
API1 --> R[Shard Router]
API2 --> R
subgraph A[Shard A]
PA[(Primary)] -.->|Replicate changes| RA[(Replica)]
end
subgraph Z[Shard B]
PB[(Primary)] -.->|Replicate changes| RB[(Replica)]
end
R --> A
R --> Z
O’Reilly
O’Reilly’s design is one API server and one database, with a replica for failover. Its production tool sends shorten requests and the requests to change a link’s target:
graph TB
T[Production Tool] -->|Shorten, change target| API[API Server]
B[Browsers] -->|Follow| API
API --> P[(Primary)]
P -.->|Replicate changes| RP[(Replica)]
Three designs
| Decision | t.co |
Drive | O’Reilly |
|---|---|---|---|
| Redirect | 302, 5 min |
302, no-store |
302, no-store |
| Database | Relational | Relational | Relational |
| Cache | Yes | No | No |
| Replicas | Reads, failover | Reads, failover | Failover |
| Sharding | By code, hashed | By code, hashed | None |
| Codes | Counter, 7 | Random, 10 | Counter, 5 |
We give t.co the cache because a few links receive most of its requests. We give Drive random codes because someone who guesses a code can open the document behind it. We give O’Reilly one API server and one database because its load is small. If we built it for more load than it has, it would cost its small team more to run.