The End of "Code First" Development
For decades, software development followed a familiar pattern: gather requirements, write code, test, iterate. But AI is fundamentally changing this equation. Welcome to Spec-Driven Development—where specifications become the source of truth and AI handles the implementation.
What is Spec-Driven Development?
Spec-Driven Development (SDD) is a methodology where specifications are the primary artifact—not code. You define what you want to build in precise, machine-readable specifications, and AI agents generate, validate, and maintain the implementation.
Traditional: Requirements → Code → Tests → Documentation
Spec-Driven: Specification → AI Generation → Validation → Refinement
The Core Principle
"The specification is the truth. Code is just one of many artifacts derived from it."
Instead of writing code that must be documented and tested, you write specifications that are:
- Executable: AI can generate working code from them
- Testable: Validation is built into the spec
- Documentable: Specs serve as living documentation
- Versionable: Changes are tracked in specs, not code
The Specification Stack
Level 1: Intent Specification
High-level description of what you're building:
# Intent: User Authentication System
## Goal
Allow users to securely register, login, and manage their accounts.
## Key Requirements
- Email/password authentication
- OAuth integration (Google, GitHub)
- Session management with JWT
- Password reset flow
- Rate limiting on auth endpoints
## Non-Functional Requirements
- Response time < 200ms
- Support 10,000 concurrent users
- 99.9% uptime
Level 2: Behavioral Specification
Define how the system behaves:
# specs/auth/login.spec.yaml
feature: User Login
scenarios:
- name: Successful login with valid credentials
given:
- user exists with email "user@example.com"
- user has password "SecurePass123!"
when:
- POST /api/auth/login
- body: { email: "user@example.com", password: "SecurePass123!" }
then:
- status: 200
- response contains: accessToken, refreshToken
- accessToken is valid JWT
- user session is created
- name: Failed login with invalid password
given:
- user exists with email "user@example.com"
when:
- POST /api/auth/login
- body: { email: "user@example.com", password: "WrongPassword" }
then:
- status: 401
- response contains: error message
- login attempt is logged
- rate limit counter incremented
Level 3: Contract Specification
Define interfaces and data structures:
// specs/auth/contracts.ts
import { z } from 'zod';
export const LoginRequest = z.object({
email: z.string().email(),
password: z.string().min(8).max(128),
rememberMe: z.boolean().optional().default(false),
});
export const LoginResponse = z.object({
accessToken: z.string(),
refreshToken: z.string(),
expiresIn: z.number(),
user: z.object({
id: z.string().uuid(),
email: z.string().email(),
name: z.string(),
}),
});
export const AuthError = z.object({
code: z.enum(['INVALID_CREDENTIALS', 'ACCOUNT_LOCKED', 'RATE_LIMITED']),
message: z.string(),
retryAfter: z.number().optional(),
});
Tools for Spec-Driven Development
Spec Kit
A comprehensive toolkit for spec-driven development:
# Initialize a spec-driven project
npx spec-kit init
# Generate code from specifications
npx spec-kit generate
# Validate implementation against specs
npx spec-kit validate
# Watch for spec changes and regenerate
npx spec-kit watch
Project Structure
my-project/
├── specs/
│ ├── intent.md # High-level intent
│ ├── features/ # Feature specifications
│ │ ├── auth.spec.yaml
│ │ ├── users.spec.yaml
│ │ └── payments.spec.yaml
│ ├── contracts/ # Type contracts
│ │ └── api.ts
│ └── scenarios/ # Behavioral scenarios
├── generated/ # AI-generated code
│ ├── src/
│ └── tests/
├── overrides/ # Human overrides
└── spec-kit.config.js
AWS Kiro
Amazon's spec-driven development platform:
# kiro.yaml
project: my-saas-app
specifications:
- path: ./specs
format: yaml
generation:
target: typescript
framework: nextjs
database: postgresql
agents:
- role: architect
reviews: specifications
- role: implementer
generates: code
- role: tester
validates: behavior
The AI-Powered Workflow
Step 1: Write the Specification
# Feature: Shopping Cart
## Behaviors
1. User can add items to cart
2. User can update item quantities
3. User can remove items
4. Cart persists across sessions
5. Cart calculates totals with tax
## Constraints
- Maximum 100 items per cart
- Items must have available inventory
- Prices locked for 30 minutes after adding
## API Endpoints
- POST /cart/items - Add item
- PATCH /cart/items/:id - Update quantity
- DELETE /cart/items/:id - Remove item
- GET /cart - Get cart with totals
Step 2: AI Generates Implementation
$ spec-kit generate features/cart.spec.yaml
Generating from specification...
✓ Created: src/cart/cart.service.ts
✓ Created: src/cart/cart.controller.ts
✓ Created: src/cart/cart.repository.ts
✓ Created: src/cart/cart.dto.ts
✓ Created: tests/cart/cart.service.test.ts
✓ Created: tests/cart/cart.e2e.test.ts
Generated 6 files, 847 lines of code
Step 3: Validate Against Specification
$ spec-kit validate
Running specification validation...
✓ Cart can add items (23ms)
✓ Cart enforces 100 item limit (15ms)
✓ Cart checks inventory availability (31ms)
✓ Cart calculates tax correctly (12ms)
✗ Cart locks prices for 30 minutes (FAILED)
Expected: price locked for 1800 seconds
Actual: price not locked
4/5 scenarios passed
1 scenario requires implementation fix
Step 4: Iterate with AI
$ claude "fix the price locking scenario in the cart specification"
Analyzing specification violation...
The cart service needs to store the price at add-time
and validate against it during checkout.
Updating: src/cart/cart.service.ts
- Added priceLockedAt timestamp to cart items
- Added price validation on checkout
- Added cleanup job for expired price locks
Running validation...
✓ All 5 scenarios passed
Benefits of Spec-Driven Development
1. Single Source of Truth
No more drift between documentation, code, and tests:
Specification
↓
┌──┴──┐
↓ ↓
Code Tests ← Both derived from same spec
↓ ↓
└──┬──┘
↓
Documentation ← Auto-generated
2. Faster Iteration
Change the spec, regenerate everything:
# specs/cart.spec.yaml
- maximum_items: 100
+ maximum_items: 200
$ spec-kit generate
Updated 3 files in 2.3 seconds
3. AI-Native Development
Specifications are perfect prompts for AI:
# AI can understand and work with specs directly
spec = load_spec("cart.spec.yaml")
code = ai.generate_implementation(spec)
tests = ai.generate_tests(spec)
docs = ai.generate_documentation(spec)
4. Better Collaboration
Non-technical stakeholders can review specs:
# Feature: Subscription Billing
## As a user, I want to:
- Choose a subscription plan
- Update my payment method
- Cancel my subscription
- Receive invoices via email
## Business Rules:
- Pro-rata refunds on downgrades
- 14-day free trial for new users
- Grace period of 3 days for failed payments
5. Guaranteed Compliance
Specs serve as executable requirements:
compliance:
gdpr:
- user data exportable within 24 hours
- user data deletable within 72 hours
- consent tracked for all data collection
pci:
- card data never stored in logs
- card data encrypted at rest
- access to card data audited
Best Practices
1. Start with Intent
Always begin with clear intent before diving into details:
# BAD: Starting with implementation details
POST /api/v1/users with JSON body containing email and password...
# GOOD: Starting with intent
We need a way for new users to create accounts so they can
access premium features and save their preferences.
2. Use Layered Specifications
Different audiences need different detail levels:
Executive Layer: "Users can securely authenticate"
Business Layer: "Support email + OAuth, implement MFA"
Technical Layer: Detailed API contracts and scenarios
3. Version Your Specs
Track changes like code:
git log --oneline specs/
a1b2c3d Update cart max items from 100 to 200
e4f5g6h Add subscription cancellation flow
i7j8k9l Initial authentication specification
4. Keep Specs DRY
Reference shared definitions:
# specs/shared/pagination.yaml
pagination:
page: integer, min 1, default 1
limit: integer, min 1, max 100, default 20
# specs/features/products.yaml
endpoints:
GET /products:
parameters:
$ref: '../shared/pagination.yaml#/pagination'
5. Include Negative Scenarios
Specify what should NOT happen:
scenarios:
- name: Cannot access other user's data
given: User A is authenticated
when: GET /users/{userB_id}/private-data
then:
- status: 403
- no data leaked in response
- security event logged
Implementing in Your Team
Phase 1: Pilot (Weeks 1-2)
- Choose one new feature
- Write specification first
- Use AI to generate initial implementation
- Validate and refine
Phase 2: Adopt (Weeks 3-4)
- Expand to more features
- Create specification templates
- Train team on spec writing
- Establish review process
Phase 3: Scale (Month 2+)
- Migrate existing features to specs
- Build spec library and patterns
- Integrate into CI/CD pipeline
- Measure and optimize
The Future of Development
Spec-Driven Development isn't just a methodology—it's a glimpse into the future where:
- Humans define intent, AI handles implementation
- Specifications are living documents that drive everything
- Code becomes disposable, specs are the asset
- AI agents collaborate to build, test, and deploy
2024: Developers write code
2025: Developers write specs + guide AI
2026: Developers write intent + review AI output
2027: Developers define outcomes + trust AI systems
Conclusion
Spec-Driven Development represents a fundamental shift in how we build software. By making specifications the primary artifact and leveraging AI for implementation, we can:
- Build faster with fewer bugs
- Maintain clearer documentation
- Enable better collaboration
- Prepare for an AI-augmented future
The question isn't whether to adopt spec-driven development—it's when. The tools are ready, the AI is capable, and the methodology is proven.
Start small, iterate fast, and let your specifications drive your success.
Ready to transform your development workflow? Book a consultation to explore spec-driven development for your team.