Blog/Why Spec Driven Development Breaks Down in Enterprise Teams

Why Spec Driven Development Breaks Down in Enterprise Teams

SDD works great when one developer knows the whole codebase. When teams and AI agents are involved, the same approach breaks in five predictable ways.

Rishi Lahoti
Rishi Lahoti
June 4, 2026·13 min read
Architecture diagram showing how spec driven development breaks across teams — ideal state vs team reality vs spec drift

GitHub's 2024 Octoverse report found that 97% of developers are using or evaluating AI coding tools. The tooling is everywhere. What isn't everywhere is the infrastructure to use it well.

The gap shows up fast. Teams adopt AI agents, see early wins on isolated features, then start shipping things that are technically functional and architecturally wrong — duplicate tables, misrouted calls, integrations to providers that were deprecated two quarters ago. The code passes review. The tests pass. Production tells a different story.

That's a context problem, not a tooling problem. And spec-driven development is supposed to be the fix.

Key Takeaways

  • SDD works reliably when one developer owns the full codebase — spec accuracy comes from direct system knowledge
  • In teams, specs are consistently written without knowledge of what already exists, causing agents to build the wrong thing correctly ([PERSONAL EXPERIENCE])
  • The five failure modes are predictable: blind specs, fragile documents, context noise, zero PM visibility, and cross-repo drift
  • The fix isn't a different methodology — it's infrastructure that connects the spec to the actual codebase

Planning before building: the core idea

AI agents are execution engines. They take a clear description of what to build and produce code that matches it. What they're not built to do is figure out what should be built, how it should interact with existing infrastructure, or whether something similar already exists three services away.

Spec-driven development keeps those decisions in human hands. The workflow runs in three stages before an agent ever opens a file: first, define the feature clearly enough that there's no ambiguity about what done looks like; second, map the technical approach against the actual system — which service owns this, what data model fits, which APIs are involved; third, break that into tasks small enough to hand off one at a time.

flowchart LR A["Spec\nwhat to build"] --> B["Plan\nhow to build it"] --> C["Tasks\nordered steps"] --> D["Agent\nbuilds it"] style D fill:#fdf6f8,stroke:#853953,color:#853953

The agent gets a task with a clear scope. It builds. The human already made every decision that mattered.

[INTERNAL-LINK: AI coding agent best practices → guide on structuring prompts and tasks for AI agents]

The scenario where this works perfectly

Imagine a developer who has owned a codebase for two years. Before writing a spec, they don't need to look anything up. They know which service handles user preferences, when the team switched SMS providers, why internal calls moved to gRPC. Writing the spec is the act of converting memory into text.

That completeness is what makes the method reliable. There's no gap between what they write and what's real — the spec reflects the system because the author and the system share the same mental model.

What exists in this scenario Why specs stay accurate
Full history of every architectural decision Spec assumptions are based on facts, not guesses
Direct knowledge of every service boundary No phantom integrations or duplicate resources
Memory of every dependency and migration Agents build on the right foundation the first time
No handoff between roles before the task If a spec is wrong, one person knows and fixes it immediately

This is the condition that makes SDD work: the spec writer and the codebase share the same mental model. When that condition holds, the methodology is nearly bulletproof. When it doesn't, everything downstream inherits the error.

The condition breaks the moment a team is involved

Enterprise codebases aren't owned by one person. A PM who has run the product for two years knows the customers better than anyone — and has probably never read the source code for the notification service. A developer seven months into the role knows their assigned services deeply and knows almost nothing about the other 37.

When these two roles collaborate on a spec, the result is built from incomplete information on both sides. Take a real scenario: the team needs to add notification preferences. The PM writes a PRD that describes what customers should be able to configure. Nothing in the PRD mentions that preferences already exist in svc-users — because the PM didn't know. The developer picks up the PRD and writes a technical plan based on what they can see from their position in the codebase. They scope it to the User model. The agent builds it exactly as described.

flowchart LR PM["PM\nno codebase context"] --> PRD["PRD\nbuilt on guesses"]:::bad --> Dev["Dev\npartial knowledge"] --> Plan["Plan\narchitecturally wrong"]:::bad --> Agent["Agent\nbuilds exactly\nwhat it was told"]:::bad classDef bad fill:#fff5f5,stroke:#e25555,color:#c04040

Clean code. Passing tests. A duplicate data layer that's going to cause problems for the next team that touches this service.

The agent did nothing wrong. The spec did.

Five ways SDD breaks at team scale

These aren't edge cases. They're the predictable result of applying solo-developer tooling to a team environment. Every one of them shows up within the first two sprints.

Failure mode 1 — The spec is written against assumptions, not facts. Nobody has queried the codebase before writing the PRD. The feature gets specced as if nothing relevant already exists. The agent builds from the spec. The spec doesn't know what's actually there.

What the spec assumed What was already in the codebase
Notification preferences need to be built svc-users has had a preferences schema for 18 months
Twilio is the right SMS integration The team migrated to a different provider last quarter

Failure mode 2 — Monolithic specs can't absorb change safely. A single spec document means every section is entangled with every other section through shared assumptions. Change the SMS behavior and something in the auth section might now be wrong — but nobody re-reads the whole document to check. Specs accrue edits and drift from reality. Agents build against whatever version they received.

Failure mode 3 — Context overload degrades agent output. Split a feature across parallel workstreams and every agent gets the full spec. The sections irrelevant to its work aren't neutral — they add noise that pulls the agent's reasoning in directions that don't apply to its task.

flowchart TD Spec["SPEC.md\n40 pages"] --> A["Agent A: email\n✓ email section\n✗ SMS 12p noise\n✗ push 8p noise\n✗ auth 6p noise"] Spec --> B["Agent B: SMS\n✗ email 10p noise\n✓ SMS section\n✗ push 8p noise\n✗ auth 6p noise"] Spec --> C["Agent C: push\n✗ email 10p noise\n✗ SMS 12p noise\n✓ push section\n✗ auth 6p noise"]

Failure mode 4 — Stakeholders go dark the moment the spec leaves their hands. Once the PM submits the PRD, their line of sight into the build closes. What shipped, what changed, what's stuck — none of it surfaces until the next standup. Checking means interrupting someone.

flowchart LR A["PRD handed off\nPM's last touchpoint"] --> B["no visibility\ncan't check progress\nor blockers"]:::bad --> C["Standup\nPM finds out"] classDef bad fill:#fff5f5,stroke:#e25555,color:#c04040

Failure mode 5 — Specs in separate repos silently contradict each other. A feature touching frontend and backend lives in two repositories. Each repository's spec evolves independently. There's no synchronization. By the time the contradiction surfaces, agents on both sides have been building against incompatible versions for days.

flowchart LR FE["Frontend repo\nSPEC.md v1\n✓ matches backend"]:::ok <--> BE["Backend repo\nSPEC.md v1\n✓ matches frontend"]:::ok classDef ok fill:#f0fdf4,stroke:#10b981,color:#10b981

The frontend spec gets updated. The backend spec gets updated. Neither update reaches the other side.

flowchart LR FE["Frontend repo\nSPEC.md v4\n✗ API contract unknown"]:::bad --"not in sync"--- BE["Backend repo\nSPEC.md v3\n✗ UI flow unknown"]:::bad classDef bad fill:#fff5f5,stroke:#e25555,color:#c04040

At 50 repositories this isn't a coordination challenge — it's structural. There is no mechanism for a SPEC.md file to know when another SPEC.md file changed. The premise that the spec is the source of truth collapses when there are dozens of specs and no relationship between them.

[INTERNAL-LINK: managing AI agents across multiple repos → guide on multi-repo AI development workflows]

What team-scale SDD actually requires

The discipline holds. Write the spec first, make every decision before the agent starts, keep scope tight. What needs to change is the infrastructure underneath it.

flowchart LR A["PRD\nknows the codebase"]:::accent --> B["Workstreams\nindependent tracks"]:::accent --> C["Requirements\nsmall, testable"]:::accent --> D["Agent\npulls its requirements"] classDef accent fill:#fdf6f8,stroke:#853953,color:#853953

Requirement 1: Ground the PRD in current system state. Before a PM writes a single line of requirements, they should be able to query the codebase in plain language. "Does a preferences schema already exist? Which service owns it? What providers are currently integrated for SMS?" The answers should come from the actual code, not from documentation that may be months out of date. A PRD built on current facts produces a plan built on current facts.

Requirement 2: Structure features as independent workstreams. Instead of one document with 40 interdependent pages, model the feature as a set of tracks — email, SMS, push — each with its own requirements and its own acceptance criteria. Changing one track doesn't require reviewing the others. Completion is visible at the track level. When scope shifts, one requirement changes and the rest are untouched.

Requirement 3: Scope each agent to its workstream. When three teams are building in parallel, each agent should receive only the requirements relevant to its work. The agent on SMS preferences shouldn't be processing email logic. Smaller context means cleaner decisions, and the agent marks completion directly against the requirements it was given.

Requirement 4: Progress as a continuous property, not a standup artifact. When a requirement is done, that status should be immediately visible to the PM and EM without anyone asking. When something is blocked, it surfaces automatically. Real-time visibility into spec completion isn't a reporting feature — it's what keeps non-engineering stakeholders in the loop without generating interruptions.

Requirement 5: One spec that spans all repos. Requirements live at the feature level, not the repository level. Frontend and backend don't maintain separate spec files that drift apart — they reference the same requirements. When something changes, it changes in one place, and every agent across every repository picks up the same version.

Without this infrastructure With this infrastructure
PRD written from memory and Confluence PRD grounded in live codebase state
One massive document, fragile to edit Independent workstreams, safe to update
All agents receive the full spec Each agent receives only its requirements
Status exists in engineers' heads Completion tracked in real time for everyone
One spec per repo, all of them drifting One spec per feature, regardless of repo count

SDD is the right call. The version that works for a solo developer doesn't translate directly to enterprise — not because the method is wrong, but because the method was never designed for teams where the spec writer doesn't have the full picture, where features span dozens of services, and where agents are shipping changes faster than anyone can manually synchronize documentation. The fix is infrastructure: a spec that's connected to the codebase, structured for parallel work, scoped to what each agent actually needs, and singular regardless of how many repos the feature touches.

See how Enact makes SDD work at scale

Connect your spec to your codebase. Keep one source of truth across every repo.

Book a call →

Frequently Asked Questions