On this page
Spec-Driven Development: A Worked Example
A complete spec for one endpoint: goal, contract, rules, acceptance criteria, and non-goals. The same structure scales to a migration.
Quick answer
- A useful spec for one feature fits on a page: goal, API contract, business rules, acceptance criteria, and non-goals.
- The acceptance criteria are the part that makes the spec verifiable; each one should map to a test and describe observable behaviour.
- The non-goals section prevents scope creep, which is the most common way an AI-generated implementation drifts.
- Write the spec before the implementation and review it like code: a pull request with a diff and comments.
- After merge, keep the tests as the durable record and archive the spec unless it remains accurate documentation.
What does a minimal feature spec look like?
Use a fixed structure so reviewers know where to look: a one-paragraph goal, the interface, the rules, the acceptance criteria, the non-goals, and the rollout notes. The structure is deliberately short. A spec that takes an hour to read will be skimmed, and the skimming is where the ambiguity returns.
The example here is a CSV export endpoint for an existing orders service. It is small enough to fit on a page and contains every element that a larger spec needs: a contract, validation rules, failure behaviour, and a decision about scale.
# Spec: CSV export for orders
## Goal
Let an authenticated user download their orders as a CSV file,
up to 100,000 rows, without blocking the request thread.
## Interface
GET /api/orders/export?from=2026-01-01&to=2026-03-31
Auth: bearer token, user scoped
200: text/csv; header Content-Disposition: attachment
400: invalid or inverted date range
401: missing/expired token
429: more than one export per user per minute
## Rules
- Only the caller's orders are included; no cross-tenant rows.
- Dates are inclusive, interpreted in UTC.
- Columns: id, created_at, status, total_cents, currency.
- Amounts are integer cents, never floats.
## Acceptance criteria
- A user with 3 orders in range receives 3 data rows plus a header.
- A user with 0 orders receives a header and no data rows.
- from > to returns 400 and no file.
- A request for another user's order id returns no row.
- A second request within 60 seconds returns 429.
## Non-goals
- Email delivery, scheduled exports, XLSX, multi-tenant admin export.
## Rollout
- Feature flag off by default; enable for internal accounts first.How do you go from spec to implementation?
Turn each acceptance criterion into a test before generating code. Then break the work into steps that can be reviewed separately: the route and authentication, the query and serialisation, the rate limit, and the flag. Give the assistant one step at a time, with the spec as context, instead of the whole feature in one prompt.
Review the result against the spec rather than against the diff alone. The diff tells you what changed; the spec tells you whether the change is the one you asked for. The non-goals are especially useful here, because generated code tends to add plausible extras that nobody requested.
How do you verify the result?
Run the acceptance tests, then check the behaviour the tests cannot see: the Content-Disposition header, the CSV encoding, the ordering of rows, and the rate-limit boundary at 59 and 61 seconds. Add one test for an empty result and one for a very large result, because those are where pagination and memory assumptions fail.
Check the failure paths too. An export endpoint that streams a partial file before hitting an error leaves the user with a corrupt download. Decide whether the implementation buffers or streams, and whether a mid-stream failure is acceptable. That decision belongs in the spec, not in a code review after the fact.
Where this bites vibecoders
Given the same endpoint without a spec, an assistant will often load every matching row into memory, forget the tenant filter, format money as a float, and add an email option because exports usually have one. Each of those is prevented by a line in this spec, which takes less time to write than reviewing the generated code.
Where AI coding assistants get this wrong
- Describing the endpoint without stating the tenant isolation rule.
- Leaving money as a float because the model defaulted to a number type.
- Omitting the rate limit, then discovering it during an incident.
- Writing acceptance criteria as implementation steps instead of observable outcomes.
- Skipping non-goals, so the assistant adds email delivery and scheduling.
- Generating the whole feature in one pass with no reviewable steps.
Checklist
- Write the goal in one paragraph.
- Specify the request, responses, and error codes.
- State the rules, including tenant isolation and units.
- Write five observable acceptance criteria.
- List non-goals explicitly.
- Turn each criterion into a test before implementation.
FAQ
How long should a feature spec be?
One page is enough for most single-endpoint features. If it grows beyond that, split the feature or move detail into a linked design doc. The spec’s job is to remove ambiguity, not to document every implementation detail; the tests and code carry the rest.
Should the spec include code?
A contract sketch helps: a request and response example, a schema fragment, or a type signature. Full implementations do not, because they lock in a solution before review and invite the assistant to copy rather than reason. Show the boundary, not the internals.
Who should review the spec?
At least one person who understands the domain and one who will operate the result. The domain reviewer catches wrong rules; the operator catches missing failure behaviour, rate limits, and rollout concerns. For a solo project, review it yourself against a checklist before generating code.
What happens to the spec after shipping?
Either maintain it as documentation or archive it. The failure mode is leaving it in place while the code evolves, so it becomes a confident description of a system that no longer exists. If the tests are good, they are the durable specification; the prose can retire.
Related topics
- What Is Spec-Driven Development?
- How to Write a Spec an AI Coding Agent Can Actually Follow
- How to Write Acceptance Criteria an AI Agent Can Verify
- Spec-Driven Development vs TDD: Which Comes First?
- How to Review AI-Generated Code Like a Senior Engineer
- Spec-Driven Development Tools Compared