Hermes Wiki
Developer/Auth/IdentityLifecycle/CaseStudies/coinbase-fragment-apis-and-federated-identity-at-1-5m-reads-second

Coinbase: Fragment APIs and Federated Identity at 1.5M Reads/Second

Problem + constraints

Coinbase's Users service is a hard dependency for nearly every critical user journey — login, trading, account management — which made it a single, monolithic service that every other team's request path ran through. Two problems compounded as Coinbase grew:

  • Coupling across unrelated domains. Fields like PhoneNumbers and UserAgreements lived in the same service and the same data store as everything else. A slowdown or bad deploy in one low-traffic fragment could degrade the entire Users service, even for callers who never touched that fragment.
  • Unpredictable, bursty load. Crypto market volatility drives read traffic that spikes hard and fast — nothing like the smoother diurnal patterns most services are built for. A monolith sized for average load falls over at the peaks that matter most.
  • Observability was a nightmare. With every kind of user data flowing through one service and one data store, isolating which fragment was actually responsible for a latency spike or an incident was slow and error-prone.

The constraint wasn't "make it faster" in isolation — it was scaling reads to 1.5M/sec during market surges without losing the consistency guarantees identity data requires (a stale permissions read or a stale account-status read is a correctness bug, not just a UX blemish).

Solution

Coinbase decomposed the monolithic Users service into Fragment APIs: each logical piece of user data (phone numbers, user agreements, account settings, etc.) gets its own independently-served API, backed by its own independent data store. A high-traffic fragment like PhoneNumbers can now scale — and fail — independently of a low-traffic fragment like UserAgreements, instead of them sharing fate through a common service and datastore.

Three pieces make the federation work as a system rather than just a pile of smaller services:

  1. Federated storage. Each fragment owns its own datastore, so scaling decisions (read replicas, caching, sharding) are made per-fragment based on that fragment's actual traffic shape, not the union of every fragment's traffic.
  2. Fragment Events. For consumers that need push-based updates rather than polling, Coinbase exposes database CDC (Change Data Capture) as event streams — critically, using the exact same data models as the read APIs. Clients don't have to learn two different shapes of the same data depending on whether they're pulling or subscribing.
  3. Freshness Tokens — the mechanism that keeps this fast and correct. A Freshness Token is an opaque identifier bound to a specific version of a resource. When a client performs a write, it gets back a token for that write. If it needs to read that data immediately afterward (read-your-writes), it presents the token, and the service guarantees the response is at least as fresh as that version — bypassing cache if the cached copy is older. This means the system can default to aggressively caching reads for the 1.5M/sec common case, without sacrificing correctness for the specific caller that just wrote the data.

Offline analytics is deliberately decoupled from the hot path: fragment data lands in Snowflake with an hourly ingestion lag, so heavy analytical queries never compete with live traffic.

What to steal

  • Freshness Tokens are the reusable idea here, independent of Coinbase or crypto. Any system that wants to cache aggressively for the 99% read-heavy case but still guarantee read-your-writes for the caller that just mutated data can use this pattern: return a version token on write, let callers optionally present it on read, and let the read path decide whether to serve from cache or bypass it. It's a cheaper, more targeted tool than "always bypass cache after a write" or "make writes and reads go through the same consistency tier."
  • Decompose by data ownership, not by traffic volume. The fragment boundary is drawn around who owns and reasons about a piece of data (phone numbers vs. legal agreements), not around arbitrary load-balancing lines — that's what lets each fragment's team make independent scaling and reliability tradeoffs.
  • One data model, two delivery mechanisms. Making Fragment Events emit the same shape as the Fragment APIs is a small design choice that prevents an entire class of "the event stream and the API disagree" bugs and integration friction.

Engineering Lens

This is a textbook example of the tradeoff you'd defend in an architecture review between a shared platform service and per-domain decomposition: the monolithic Users service was simpler to reason about as a single system, but it meant every fragment inherited the blast radius and scaling ceiling of the whole. The Freshness Token detail is the part worth internalizing beyond the decomposition itself — it's a concrete answer to "how do you get aggressive caching and strong-enough consistency in the same system" that doesn't require picking one model globally. In a review, this is the kind of decision you'd frame as "we're trading a small amount of client-side complexity (present a token you already have) for a large win in default cache hit rate" — a good example of pushing a consistency decision to the edge where the caller actually knows whether they need it, rather than centralizing a conservative default that punishes everyone.

Hermes Wiki