What Is Spec-Driven Development and Why Does It Matter?
Spec-driven development (SDD) flips the typical AI coding workflow. Instead of asking an AI to write code and hoping it matches your intent, you write the intent first — in a structured, unambiguous spec — and the AI implements against it. The spec defines scope, constraints, acceptance criteria, and edge cases before any code is generated.
This matters because AI coding assistants are fast but context-hungry. A scattered chain of prompts, also called “vibe coding,” produces code that drifts from the original goal. Each new prompt risks reintroducing assumptions, breaking constraints, and creating technical debt. SDD forces the hard thinking up front and gives the AI a stable target to aim at.
Why Vibe Coding Fails at Scale
Vibe coding works for prototypes and one-off scripts. It fails when:
- The feature spans multiple files or modules
- Multiple engineers review or iterate on the output
- The code must follow existing architecture, security, or style rules
- The feature needs to be maintained over months
The problem is context decay. The AI does not remember your entire codebase unless you feed it every time. Each prompt is a fresh conversation with partial context. Without a spec, the AI optimizes for the immediate request, not the long-term health of the system.
The Three Levels of SDD Rigor
SDD is not one size fits all. Teams operate at three levels depending on risk, compliance needs, and tooling maturity.
Level 1: Spec-First
You write a lightweight requirements document before generating code. The spec is a planning artifact. Once the feature is implemented, the spec may be archived or left behind.
Best for: Internal tools, prototypes, low-risk features.
Tradeoff: Better than no spec, but the spec does not protect against future drift.
Level 2: Spec-Anchored
The spec is a living document. It evolves with the code and is used for maintenance, debugging, and future iterations. The AI references the spec every time it touches the feature.
Best for: Production systems, team projects, features with ongoing maintenance.
Tradeoff: Requires discipline to keep the spec and code in sync.
Level 3: Spec-as-Source
The spec is the sole source of truth. Humans edit only the spec. Code, tests, and binaries are generated byproducts. This is the most radical form and requires the most mature tooling.
Best for: High-compliance environments, generated systems, or teams building AI-native products.
Tradeoff: Full adoption is hard and not appropriate for every codebase.
| Level | Human Edits | Spec Lifetime | Best For |
|---|---|---|---|
| Spec-First | Spec + code | Until implementation | Prototypes, low-risk |
| Spec-Anchored | Spec + code | Ongoing | Production systems |
| Spec-as-Source | Spec only | Permanent | High-compliance, AI-native |
Spec-First vs. Spec-Once
Most teams think they are doing spec-first development when they are actually doing spec-once. They write a detailed spec at the start of the project, then abandon it once implementation begins. The spec launches the work but does not guide it.
This is the easiest trap to fall into with AI coding tools. The spec helps you define the first prompt. Then the excitement of generation takes over. The AI starts writing code, the project grows, and the original document gathers dust.
Real spec-driven development is a continuous feedback loop. The spec is not a launch checklist. It is the steering document. You revisit it when you discover edge cases, when you change architecture, and when you hand the work to another agent or teammate. The value is not the initial drafting. The value is the discipline of forcing yourself to think about requirements before acting on them.
How to Write a Spec That AI Can Execute
A good SDD spec is not a prose document. It is a structured contract with explicit sections. The AI should be able to read it and know exactly what to build, what to avoid, and how to verify success.
Required Sections
- Overview — One sentence describing the feature and the user outcome.
- Goals — What the feature must achieve.
- Non-Goals — What is explicitly out of scope.
- Constraints — Architecture, security, performance, or style rules that must hold.
- Acceptance Criteria — Verifiable conditions for completion.
- Edge Cases — How to handle error states, empty inputs, and limits.
- Dependencies — APIs, services, or files the feature interacts with.
- Verification — How the implementation will be tested or reviewed.
Example Spec for a Rate Limiter
# Rate Limiter Spec
## Overview
Implement a token-bucket rate limiter that protects the public API from abuse.
## Goals
- Enforce per-user request limits.
- Return clear 429 responses with Retry-After headers.
- Support both in-memory and Redis backends.
## Non-Goals
- Global rate limiting across all users.
- Billing or metering integration.
## Constraints
- Must use the existing Redis client in `lib/redis.ts`.
- Must not add more than 5ms of latency per request.
- Must follow the TypeScript style in `src/middleware/`.
## Acceptance Criteria
- [ ] 1000 requests per minute per user are allowed.
- [ ] 1001st request returns 429 with a Retry-After header.
- [ ] Redis backend is configurable via env var.
## Edge Cases
- Missing user ID falls back to IP-based limiting.
- Redis unreachable degrades to in-memory mode.
## Dependencies
- `lib/redis.ts`
- `src/middleware/auth.ts`
- `src/types/api.ts`
## Verification
- Unit tests for bucket logic.
- Integration tests for middleware behavior.
- Load test to verify latency under 5ms.
This format is not just readable by humans. It is parseable by AI. Each section gives the model a clear signal about what to do and what to protect.
Planning and Drafting the Specification
For a multi-part project, a single spec is not enough. You need a project plan that breaks work into sub-projects, phases, and testable stacks. This is especially important for infrastructure work or anything that crosses service boundaries.
A Practical Planning Pattern
- Research phase — Read the relevant documentation and point the AI at it. In Claude Code, this means using the documentation or MCP tools to ingest the same sources you read.
- Stack decomposition — Split the project into independently deployable stacks. Each stack becomes a phase. This makes testing and iteration much faster.
- Spec drafting — Write the spec for each phase. Each spec should include inputs, outputs, dependencies, and verification steps.
- Review — Read the spec before generating code. Check that the design, architecture, and sequence match your intent.
Example: Multi-Stack Agentic Gateway
Suppose you are building an AI gateway that uses a request interceptor, an MCP server, and an OAuth credential provider. A naive approach would be one stack. A better approach is three phases:
| Phase | Stack | What It Builds | Why Separate It |
|---|---|---|---|
| 1 | Interceptor | Lambda function that modifies incoming requests | Can be tested locally with SAM before the rest exists |
| 2 | MCP server | Server deployed on the runtime | Tested locally, then deployed and verified |
| 3 | Gateway | Gateway resource, target, credential provider | End-to-end integration tested last |
Each phase has its own spec. The AI implements one phase at a time, tests it, and only then moves to the next. This prevents the common failure mode where everything is generated at once and nothing works.
How to Use the Spec with AI Agents
Once the spec is written, the workflow is straightforward:
Step 1: Define the Constitution
Create a codebase-level constitution that the AI must follow in every task. This includes security rules, preferred frameworks, testing standards, and style conventions. The constitution is the foundation. The spec is the blueprint.
Constitution:
- Use TypeScript strict mode.
- Never commit secrets or credentials.
- Prefer explicit types over `any`.
- Write tests for all public functions.
- Use the existing error handling pattern in `src/errors/`.
Step 2: Draft the Spec
Write the spec as a Markdown file in the project repository. Keep it in a specs/ directory or next to the relevant code. Use the format above.
Step 3: Feed the Spec to the AI
Use a modern AI coding assistant or development kit that supports multi-agent workflows. Pass the constitution, the spec, and the relevant codebase context. Ask the AI to implement the spec, generate tests, and verify against the acceptance criteria.
Step 4: Verify the Output
Review the generated code against the spec. Do not accept the code because it compiles. Accept it because it satisfies the acceptance criteria and respects the constraints.
Working with Claude Code in Practice
Most of the discussion around SDD is abstract. The real friction appears when you sit down with an AI coding assistant and start building. Here are practical observations from using Claude Code on multi-stack infrastructure projects.
Context Windows Still Matter
Claude Code has a 200k token context window on standard Pro plans. That sounds large until you feed it documentation, multiple files, conversation history, and tool outputs. On heavy projects, especially with long AWS CloudFormation templates or multiple API docs, you can hit that limit.
When the limit is reached, Claude Code compacts the conversation history. That process can take 3–5 minutes on the low end and 10–12 minutes on complex sessions. The simplest way to avoid this is to keep the spec outside the chat and feed it back in chunks. Better yet, break the project into the small phases described above so no single session grows too large.
Model Choice Affects Usage Limits
Heavier models like Claude Opus hit usage limits much faster than Sonnet. On a Pro plan, heavy Opus use can exhaust the conversation budget in 45 minutes to an hour. Sonnet can run for several hours without hitting the same ceiling. For spec-driven work, where most of the value is in planning and structured execution, Sonnet is often sufficient. Save Opus for the hardest debugging or architectural decisions.
Use Selectable Clarifying Questions
Instead of asking the AI open-ended questions, instruct it to present a menu of options. This turns back-and-forth clarification into a single selection. For example:
Before starting, ask any clarifying questions you need.
Present each question as a numbered menu with 2–4 options.
Include "Other" as the last option and let me type a custom answer.
This removes the friction of open-ended prompts and gives you a clean summary of all decisions at the end.
Build Trust Gradually
Claude Code asks for permission before most actions. You have three options: yes, yes to this category, or no. Start restrictive. Allow read-only actions first. As you see the AI respect the spec and constitution, allow writes. Eventually, you may auto-allow certain safe categories. But avoid the --dangerously-skip-permissions flag until you have a proven, repeatable workflow. The spec is your safety guard, not a substitute for oversight.
Lessons Learned
-
Time spent planning pays off. A clear spec reduces the number of follow-up interactions from major course corrections to small tweaks.
-
Build stepwise in small, testable chunks. Each phase should be independently deployable and verifiable. This makes failures localized and recoverable.
-
Security belongs in the spec from day one. Adding OAuth or authorization at the end can force a full stack redeploy. Define the security model in the first draft.
-
Flexibility is required. The tool you want to use may not support everything you need. A good spec names fallback approaches so the AI does not get stuck.
-
Update documentation as you learn. If you course-correct during implementation, update the spec. Otherwise, the document becomes a lie and the next agent will build on bad assumptions.
-
Create a steering document. Take lessons learned and feed them back into a
CLAUDE.mdor project-level skill file. The next project starts smarter.
Why This Feels Slower But Is Actually Faster
SDD feels slower than vibe coding because you must think before you generate. But the projects that skip this step pay later. The debt shows up as:
- Re-architecting after the third iteration
- Rewriting code that drifted from the original goal
- Debugging edge cases that were never defined
- Explaining generated code to teammates who did not write the prompts
At Google, I saw the same pattern with large design docs. The teams that invested in a clear spec moved faster during implementation and had fewer surprises in production. The spec was not overhead. It was the work.
With AI, the spec is even more important. The AI is fast. It will happily build the wrong thing quickly. The spec keeps it aimed at the right thing.
When to Use SDD vs. Vibe Coding
| Scenario | Vibe Coding | Spec-Driven |
|---|---|---|
| Throwaway script | ✅ | ❌ |
| Prototype | ✅ | ⚠️ lightweight spec |
| Production feature | ❌ | ✅ |
| Multi-file change | ❌ | ✅ |
| Security-critical code | ❌ | ✅ |
| Team-reviewed feature | ❌ | ✅ |
| Long-lived system | ❌ | ✅ |
The rule is simple: if the code needs to survive beyond the current session, write a spec.
Frequently Asked Questions
Does SDD mean more documentation work?
Yes, but it replaces debugging and rework. A spec is documentation that pays for itself by preventing the AI from building the wrong thing.
Can I use SDD with any AI coding assistant?
Yes, but some tools are better than others. Claude Code, Cursor, and GitHub Copilot can all follow specs. Multi-agent frameworks like GitHub Spec Kit or custom LangChain pipelines can enforce them more rigorously.
What if the spec is wrong?
Then the AI will build the wrong thing correctly. The spec is the source of truth. Reviewing the spec is just as important as reviewing the code. SDD does not remove human judgment. It concentrates it at the right point.
How do I keep specs in sync with code?
Treat the spec as a living file. Update it when the code changes. For spec-anchored projects, make spec updates part of the code review. For spec-as-source projects, the spec is the only file humans edit.
Is SDD only for AI-generated code?
No. It works for human-written code too. The difference is that humans can tolerate ambiguity better than AI. With AI, the cost of ambiguity is much higher.
References & Further Reading
- Three Tools for Spec-Driven Development — Birgitta Böckeler on the three levels of SDD rigor
- GitHub Spec Kit — open-source framework for spec-driven development
- Anthropic Claude Code — terminal-based AI assistant that can ingest specs and code context
- Extending Claude Code with Skills and Plugins — AWS guide on custom skills and steering documents
- Building an Elite Engineering Culture — on stacked PRs and building incrementally
- Cursor — AI code editor with context-aware implementation
- LangChain Multi-Agent Workflows — patterns for coordinator and verifier agents
- Google Engineering Design Docs — how structured specs drive large engineering projects
What to Read Next
Spec-driven development is part of a broader shift: treating AI as an executor rather than an oracle. The better your spec, the better the AI performs. The next step is learning how to communicate with AI efficiently so the spec is not wasted on context decay.
- 📖 Related: AI for Understanding and Visualization: Why HTML Artifacts Beat Markdown
- 📬 Newsletter: Get AI engineering posts like this weekly → Subscribe free
- 📥 Resource: The AI Mastery Roadmap for Software Engineers