DEV Community

Davi Orlandi
Davi Orlandi

Posted on

How I Use SDD (Spec-Driven Development)

If you follow tech the way I do, you've probably already felt lost with the flood of innovations launching every week since AI took off (or at least opened Twitter/LinkedIn and thought "okay, I became obsolete in 3 days"). Today I'll share a bit of my experience with one of them: Spec-Driven Development.

What is SDD?

SDD, or Spec-Driven Development, is a software development framework where the specification comes before the code. Instead of generating code unchecked, we define functional and technical specifications that guide development, serve as documentation and history, and help enrich the context LLMs use throughout the process.

There are many ways to use SDD. You can rely on ready-made setups like cc-sdd for Claude Code, or Spec Kit Command for Cursor, which already ship with ready-to-use commands. You can also build your own commands on top of these setups to fit your day-to-day workflow. It's common to have agents, skills, or commands specialized for each company's workflows — "How to deploy the backend", "Security acceptance criteria", and so on.

Workflow

SDD implementations vary by use case, but most go through these phases:


Functional Spec

This is where we describe requirements functionally. Use as little technical language as possible (yes, that's harder than it sounds).

You can start from an idea, a task from tools like Jira via MCP, or even a bug. Example:

Users complete onboarding but receive no follow-up. That reduces engagement and doesn't guide them through the next steps inside the platform.

Since this is a discovery moment, the AI starts asking questions:

AI: Which users should we implement this for?

You: All newly registered users who finished onboarding.

AI: Exactly when should the email be sent?

You: Immediately after confirming that onboarding completed successfully.

AI: What are the functional requirements?

You:

  1. Detect the moment onboarding completes
  2. Trigger the email only once per user
  3. Personalize the email with basic data (name, etc.)
  4. Implement retry if the email service fails
  5. Log successes and errors

These refinements produce a Functional Spec — everything needed to describe the technical details of the implementation.

That document should also include clear acceptance criteria, which serve as the validation baseline throughout the flow.

The spec must be editable and have an approval mechanism. In almost every case, you'll iterate with the LLM until you land on something satisfactory.

This phase can be started with commands like:

/sdd.spec functional Envio de email de onboarding

Some setups use flags such as:

  • --clarify when something isn't clear
  • --approve when you consider the spec ready

Technical Spec

With the functional specification defined, translate the business requirements into technical details. You can start with:

/sdd.spec technical

Example:

AI: What technology stack will you use?

You: Node.js with Express for the service, integration with an email provider (e.g. SES or similar), and a queue (e.g. SQS or PubSub) for asynchronous processing.

AI: What API design approach?

You: Event-driven architecture. The trigger will be based on the user.onboarding.completed event, with asynchronous communication.

AI: Which services or platforms will be integrated?

You: An email service for sending, a messaging system for the queue, and possibly a template service. Also integration with the auth system to keep data consistent.

AI: What are the performance requirements?

You:
Event processing latency under 5 seconds
Ability to handle spikes without losing events
Failure rate under 1 percent with automatic retry

AI: How will reliability be ensured?

You:
Use a queue to decouple processing
Retry with exponential backoff
Dead-letter queue for unprocessed events
Idempotency to avoid duplicates

Just like in the functional phase, this step produces a technical document that should be reviewed and approved.

Don't let technical details rewrite the functional requirements — though in the real world, technology often ends up shaping business specs anyway.


Tasks

By now we've turned an idea into two clear things: what to do and how to do it. Next comes execution.

Translate the spec into clear, actionable tasks — exactly what the LLM or the developer should do, with no ambiguity. Start with:

/sdd.plan

The AI then generates something like:

AI: Here are the suggested tasks:

  • TASK-001: Implement consumer for the user.onboarding.completed event
  • TASK-002: Create email-sending service with provider integration
  • TASK-003: Implement idempotency logic to avoid duplicates
  • TASK-004: Create email template with personalization
  • TASK-005: Wire the full flow from event to send
  • TASK-006: Add logs and metrics
  • AUTO-TASK-001: Create unit tests
  • AUTO-TASK-002: Create integration tests

These tasks can be saved in files such as tasks.json or individually as TASK-001.md, containing:

  • Status such as wip, done, or canceled
  • Assignee
  • Dependencies
  • Possibility of parallelization

You can refine with:

/sdd.plan --refine

And then approve with:

/sdd.plan --approve

This phase matters because it turns the spec into something executable. There should be no ambiguity here — only clear tasks.


Implementation

With everything approved, enter the implementation phase:

/sdd.build

During this phase, the AI executes the tasks and continuously validates the acceptance criteria from the functional spec, keeping the implementation aligned with the plan.

Because the tasks are already well defined and decoupled, some tools let you parallelize executions that have no dependencies.

One example is Claude Agent Teams, which let you run multiple agents in parallel, each responsible for part of the system. Instead of a single AI doing everything sequentially, you can have:

  • One agent implementing services
  • Another writing tests
  • Another handling integration

All at the same time, respecting the dependencies defined in the tasks.

This works especially well with SDD because the tasks are already well scoped — you don't need to manually coordinate who does what; the structure of the spec enables that split.

Following the flow:

AI: Creating branch feature/email-onboarding

AI: Starting task execution.

AI: Running TASK-001: Event consumer

AI: Consumer created successfully. Want to validate with tests?

You: Yes.

AI: Tests ran successfully.

AI: Running TASK-002: Email-sending service

AI: Provider integration complete. Retry implemented.

AI: Tests passing.

This process continues until all tasks are done.


Finish

After implementation, wrap up the feature: make sure everything defined in the specs was delivered, validated, and is ready for production.

You can start with:

/sdd.finish

The AI then runs final validations:

AI: Checking task status...

AI: All tasks are complete.

AI: Validating tests...

AI: All tests are passing with adequate coverage.

AI: Validating consistency between specs and implementation...

AI: No divergences found.

AI: Do you want to finish the feature?

You: Yes.

At that point, a few things usually happen:

  • Mark the feature as complete
  • Ensure all specs are up to date
  • Consolidate documentation
  • Prepare for deploy or merge

Tips & tricks

Don't limit yourself to ready-made setups — you can integrate this flow with day-to-day tools using MCPs like Jira or Linear to generate specs from tasks, GitHub to manage issues, branches, and comments, or Playwright to test a generated frontend.

It's also common to have specialized agents for specific stages — code review, security validation, performance analysis. That makes the flow safer without adding manual complexity for the developer.

Conclusion

You're no longer deciding what to do while writing code. That was already settled in the earlier phases. In a world where LLMs take an active part in development, this shrinks scope, improves delivery quality, and makes the process far more reproducible.

In the end, it isn't about writing more code. It's about thinking better before you code (and letting the AI suffer a bit more in your place).

Top comments (0)