Coherent vs Random Mock Data: Why Your Fake API Keeps Lying
July 1, 2026
Most mock data is generated one field at a time. A script walks your schema, and for each field it rolls a plausible-looking value — a random UUID here, a fake name there. Each response looks fine on its own. The problem shows up the moment two responses are supposed to refer to the same thing.
The bug hiding in “realistic” data
Say GET /orders/42 returns a customerId. With per-field generation, that ID is just a random value. Now your app does what real apps do — it follows the link and calls GET /customers/<that id>. There’s no such customer. You get a 404, or worse, an empty object your UI wasn’t built to handle.
GET /orders/42
{
"id": 42,
"customerId": "9f3b1c7e-44a2-4f08-bd31",
"total": 129.00
}
GET /customers/9f3b1c7e-44a2-4f08-bd31
→ 404 Not FoundThe customerId points at a customer that doesn't exist. Your flow breaks the moment it follows the link.
GET /orders/42
{
"id": 42,
"customerId": 318,
"total": 129.00
}
GET /customers/318
{
"id": 318,
"name": "Alice Tan",
"email": "alice.tan@example.com"
}customerId: 318 resolves to the same realistic customer — everywhere it appears across your API.
This isn’t an edge case. Any data with relationships — orders and customers, posts and authors, bookings and rooms — breaks the same way. The mock is “realistic” field by field and incoherent as a whole.
What “coherent” actually means
Coherent data means the dataset agrees with itself. Every foreign key points at a record that exists. The same entity has the same values everywhere it appears. If order 42 belongs to customer 318, then customer 318 is a real, consistent customer on their own endpoint, in the list endpoint, and anywhere else they’re referenced.
You get there by generating the whole dataset together instead of per request — first deciding the entities and how they relate, then filling in values that respect those relationships.
Why hand-rolled fixtures drift
The common workaround is to hand-write fixtures — a faker script, a folder of static JSON, a Mockoon file with saved responses. It works until the spec changes. Add a field, rename an entity, split an endpoint, and your fixtures silently fall out of sync with the contract. Now the mock lies in a new way: it no longer matches the shape your real API promises.
Deriving the data from the spec removes that maintenance treadmill. When the spec changes, the mock changes with it, and coherence is preserved because it’s a property of how the data is generated — not something you patch back in by hand.
The short version
Random mock data is fine for a single screen and dangerous the moment your app navigates. Coherent data behaves like a real backend, which is exactly what you need when you’re testing flows or running a live demo. See it end to end in the 5-minute OpenAPI mock walkthrough, or read where the common tools land on this in the mock API tools comparison.