Featured image of post OpenApi- Big Decisions- Code First or Design First Approach?

OpenApi- Big Decisions- Code First or Design First Approach?

One of the biggest questions you need to answer when starting an OpenAPI project is:

Where does the OpenAPI definition live?

Or, as we used to say back in the mid-2000s:

“Where is your authoritative source?”

This question is critical because your entire API ecosystem depends on it.

When I first started using OpenAPI (then called Swagger), I did what many developers still do today:

  1. Set up Swashbuckle in an ASP.NET Core project.
  2. Let it automatically generate swagger.json based on controllers.
  3. Use NSwag Studio to generate client proxy classes for consuming the API.

For internal APIs with a technical audience, this is fast, simple, and lean.

πŸ”Ή Change an API controller?
➑️ Swagger updates automatically.

πŸ”Ή Using CI/CD scripts to generate client proxies
➑️ If there’s a breaking API change, depending on the change something - somewhere will likely fail to build- so you know you broke something

This approach is great for sensing change, but is it the best long-term strategy?


🚨 The API Design Dilemma: Code-First vs. Design-First

When building APIs, you have two approaches:

1️⃣ Code-First (Generate OpenAPI from Code)

βœ… Use tools like Swashbuckle (C#), FastAPI (Python), or SpringDoc (Java) to generate OpenAPI from controllers.
βœ… API changes automatically reflect in OpenAPI docs.
βœ… Fast and lightweight for internal teams.
❌ API design is tightly coupled to the implementation.
❌ No clear API review process before implementation.
❌ Can result in inconsistent API design over time.

2️⃣ Design-First (OpenAPI Defines the Code)

βœ… Use visual tools like Stoplight Studio, Swagger Editor, or Postman to design APIs.
βœ… The OpenAPI spec becomes the single source of truth.
βœ… Code is generated from OpenAPI rather than the other way around.
βœ… Encourages API governance, consistency, and review before implementation.
❌ Requires discipline to keep code in sync.
❌ More upfront effort.

πŸ”‘ Key Difference?

  • Code-First = “Write Code, Docs Follow”
  • Design-First = “Write API Spec, Code Follows”

πŸ›  Tools for API Design-First Workflows

ToolPurposePros
Stoplight StudioVisual API editorNo YAML needed, built-in mocking
Swagger EditorOpenAPI editor in the browserSimple, fast, free
PostmanAPI design & testingGreat for team collaboration
ApicurioAPI governance & lifecycle managementIdeal for large teams

With these tools, API design comes first.
Developers then use the OpenAPI definition to generate code stubs instead of letting the code generate OpenAPI.


πŸ”„ Code-First vs. Design-First: Pros & Cons

FeatureCode-First (Swashbuckle, NSwag)Design-First (Stoplight, Swagger Editor)
Speedβœ… Fast setup⚠️ Slower initial setup
Documentation⚠️ Auto-generated, but not always user-friendlyβœ… Structured, well-documented APIs
Consistency❌ Can be inconsistent between teamsβœ… Encourages standardization
Collaboration❌ Harder to collaborate before implementationβœ… API design is reviewed before coding
Breaking Changesβœ… CI/CD detects breaking changes❌ Manual validation required
Long-Term Maintainability⚠️ Can get messy over timeβœ… More scalable

πŸ— Code-First for Internal APIs, Design-First for Public APIs

So which approach should you use?

πŸ”Ή For internal, tech-focused APIs?
➑️ Code-first is fast and good enough (Swashbuckle + NSwag).

πŸ”Ή For public, customer-facing APIs?
➑️ Design-first ensures consistency, better documentation, and API governance.

Hybrid Approach?
You can start with Code-First and transition to Design-First as your API grows.


πŸ”₯ How to Implement Design-First API Development

If you’re moving toward Design-First, here’s a solid workflow:

1️⃣ Design the API First

Use Stoplight Studio or Swagger Editor to draft the API before coding.

2️⃣ Generate Code Stubs

Use tools like NSwag, OpenAPI Generator, or AutoRest to generate controllers/models.

Example: Generate C# API controllers:

1
npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g aspnetcore -o ./output

3️⃣ Keep API & Code in Sync

  • Validate API updates using Spectral Linting:
    1
    
    spectral lint openapi.yaml
    
  • Use contract tests (like Pact) to verify API behavior.

4️⃣ Automate API Documentation

Deploy OpenAPI docs with ReDoc or Swagger UI:

1
docker run -p 8080:80 -v $(pwd)/openapi.yaml:/usr/share/nginx/html/openapi.yaml redocly/redoc

πŸ”₯ Conclusion: Pick Your Source of Truth Wisely

πŸ‘‰ If code generates OpenAPI (Code-First), your API evolves organically but may lack consistency.
πŸ‘‰ If OpenAPI defines the code (Design-First), your API is structured and governed, but requires discipline.

For small, internal APIs, stick with Swashbuckle + NSwag.
For public APIs, shift to Design-First with Stoplight or Swagger Editor.

At the end of the day, the most important thing is to choose your authoritative source earlyβ€”because fixing API design later is painful. πŸ˜…


πŸ”‘ Key Takeaways

SummaryDetails
What is the “Single Source of Truth”?The authoritative place where your API is defined.
Code-First Approach?API is defined by implementation, OpenAPI is auto-generated.
Design-First Approach?OpenAPI is written first, then code is generated from it.
Best for Internal APIs?Code-First (Swashbuckle + NSwag).
Best for Public APIs?Design-First (Stoplight, Swagger Editor, Postman).
How to switch to Design-First?Use OpenAPI design tools, generate stubs, and automate validation.