A GraphQL connection field takes no ordering argument. What order should the server return, and why must it be pinned?
answer
- No argument still means an order
- Unordered results are not reproducible
- Plans, replicas and parallel scans differ
- Pin it, make it total, document it
- No specification defines a default
basics
~20 sThe server must choose one total order, use it for every request of that field, and document it. "Whatever the backend returned" is not an order — it can differ between two identical requests, which makes every cursor meaningless.
solid answer
~50 sA field with no ordering argument has still made an ordering decision; the only question is whether anyone made it deliberately. Forwarding a fetch with no ordering instruction gives no order at all, and results can legitimately arrive in a different sequence on each execution — a different plan, a parallel scan, a different replica, a caching layer in between. Cursors handed out under one sequence are meaningless under the next. So pin a default: pick the order callers actually want (for a clinic feed, newest appointments first), make it **total** by appending a unique immutable tie-breaker, apply the identical order on the first page and on every resume, and write it in the field's description so it travels through introspection. Nothing in the GraphQL specification or the Cursor Connections (Relay server) specification defines or declares a default order — it is contract you write yourself.
code
graphql · 8 linestype Clinic {
"""
Appointments for this clinic, newest first.
Order is always (scheduledAt DESC, id DESC): total, and identical
for the first page and every resume.
"""
appointments(first: Int, after: String): AppointmentConnection!
}go deeper
Know that a list of rows has no inherent order and that a server which does not sort can return the same rows in a different sequence next time. That alone explains why a connection needs a chosen default.
Explain what makes an unsorted result non-reproducible — plan changes, parallel execution, replicas, caching — and state the three things a default needs: chosen deliberately, total, and applied identically on the first page and every resume.
Show you treat the default order as contract: how you pick it from what callers need, why it must be cheap to serve and resume, where you document it so introspection carries it, and what breaks when a plan change silently reverses an order clients had already come to depend on.
Own the policy across a large graph: every paged field declares a total default in its description, changes to a default are announced like contract changes, and the paging layer is shared so no team ships a field whose order is whatever the query planner felt like.
## "Unordered" is not a default order A connection field with no ordering argument still has an order — the one the server chose, whether or not anyone chose it deliberately. The failure mode is a field that simply forwards a fetch with no ordering instruction and returns rows in whatever sequence came back. That is not a weak order; it is **no order at all**, and a result set with no order cannot support cursors, because a cursor's whole meaning is "the position after which the next page begins" and positions only exist inside an order. The reason "whatever the backend returned" varies is worth being able to state concretely, because juniors often assume a table has a natural sequence: - A different execution plan can be chosen for the same request as data volumes or statistics change. - A parallel scan can interleave its workers differently on each run. - A read spread across replicas can hit a replica whose physical layout differs. - Rows that are updated can move, and re-used space changes what a scan encounters first. - Any caching layer in between can serve a differently-ordered set. Two identical requests are therefore permitted to return the same rows in a different sequence. Every cursor handed out under one sequence is meaningless under the next. ## What "pinning" the default means A default order is part of the API contract, and pinning it has four parts. **One: choose it deliberately, from what callers actually want.** For a clinic's appointment feed that is usually `scheduledAt` descending — the next thing a scheduler needs to see. Pick the order that makes the common client's first page useful, since a default order is only a default because most callers accept it. **Two: make it total.** Append a unique, immutable tie-breaker so the default is `(scheduledAt DESC, id DESC)` rather than `(scheduledAt DESC)`. A default that is not total is exactly the bug the explicit-sort case has, with less chance of being noticed, because nobody thinks of an unspecified default as a sort at all. **Three: use the identical order on every request for that field** — the first page, every resume, and every replica. If the resume path builds its ordering separately from the first-page path, the two can drift, and the drift shows up as duplicated or missing rows at the page boundary rather than as an obvious error. **Four: document it in the schema.** The field description is the right home, because descriptions travel through introspection and therefore reach every consumer and every generated client. Neither the GraphQL specification nor the Cursor Connections (Relay server) specification says anything about default ordering — there is no reserved argument, no directive and no convention for declaring it, so if it is not written in the description it exists only in someone's head. ## The judgement an interviewer is listening for The strong answer treats an unstated default as a **contract defect**, not a style preference, and reasons about it in three directions. *What clients will assume.* Consumers will infer an order from what they observe, then depend on it. A UI shipped against a feed that happens to arrive newest-first will break when a plan change reverses it, and it will break as a rendering bug rather than as an API error. Once observed, an order is depended upon, which is the argument for choosing and stating it before the first client ships. *What it costs to serve.* The default order is the one served on nearly every request, so it should be one the storage layer can produce and resume from cheaply rather than by materialising the whole collection and sorting it. A default nobody can serve efficiently is a default that will quietly be replaced by whatever the fast path returns. *What it is safe to change later.* Changing the default order changes what page one means for every existing caller, and it invalidates any cursor issued under the old order — how a server should behave when a cursor arrives from a different sort is a separate concern, but the fact that a default change *creates* those cursors is a reason to treat the default as a versioned part of the contract and not as an implementation detail to be tuned. ## A worked shape For a hospital appointment graph, `Clinic.appointments` with no ordering argument, documented as: newest first, ordered by `(scheduledAt DESC, id DESC)`, identical for every page. That single sentence in the field description does three jobs: it tells the client what page one contains, it tells the next server engineer which comparison the resume path must implement, and it tells a reviewer that the order is total. The generalisation is short. A connection is a promise that a client can walk a collection exactly once, and that promise rests entirely on the collection having one fixed, total order. An ordering argument merely lets the client pick among several such orders; when there is no argument, the server has picked, and it owes callers the same guarantee it would owe if they had asked.
- A client supplies its own partial order. Does the server still append the tie-breaker?Always. Whatever the caller asks to sort by, the server appends the unique immutable column before executing, so every order the field can produce is total. Otherwise the caller has effectively been handed a way to request a broken paging session, and the defect appears only for whichever sort key happens to have duplicates.
- Where should the default order be documented so consumers actually see it?In the field's description in the schema. Descriptions are carried by introspection, so they reach explorers, generated clients and code review without anyone reading a separate document. External prose drifts from the schema; a description ships with it. Neither specification provides a reserved argument or directive for declaring an order, so the description is the only machine-distributed place it can live.
- How much freedom do you have to change the default order later?Less than it looks. It is not a breaking change by the type-system's rules — no field or type changes shape — but it changes what page one contains for every existing caller and it invalidates cursors issued under the old order. Treat it as a versioned part of the contract: announce it, and expect clients that inferred the old order from observation to break silently.
saying these in an interview costs you the question
- Assumes rows come back in insertion or primary-key order
- Says an unordered result is fine because clients re-sort
- Treats the default order as an implementation detail
- Builds first-page and resume orders in different code paths
- Leaves the default order undocumented outside the schema
- Claims a specification defines the default connection order