When to Use Clean Architecture (And When Not To)

When to Use Clean Architecture (And When Not To)

5 min read··

clean-architecturedotnetsoftware-architecture

Clean Architecture is the default recommendation in the .NET space, and that is exactly the problem. Defaults get applied without asking whether the project has the problems the architecture solves. Sometimes four projects and a dependency diagram is the right call, and sometimes it is a five-endpoint API wearing a suit of armor. Here is a decision framework for telling the two apart.

Clean Architecture Is Not Always the Answer

Teams apply Clean Architecture to every project, regardless of complexity. A five-endpoint CRUD API with four separate projects, domain events, a CQRS pipeline, and architecture tests.

That's over-engineering.

Clean Architecture solves specific problems. When those problems don't exist, the architecture adds cost without benefit.

When Clean Architecture Shines

Complex Business Logic

If your domain has real business rules - not just CRUD operations - Clean Architecture protects that logic from infrastructure concerns.

Signals you need it:

  • Business rules that span multiple entities
  • Domain invariants that must always hold
  • Complex calculations or state machines
  • Rules that change independently from infrastructure
// This is domain complexity worth protecting
public class LoanApplication : AggregateRoot
{
    public ApplicationStatus Status { get; private set; }
    public decimal Amount { get; private set; }

    public Result Approve(CreditScore score, DebtToIncomeRatio ratio)
    {
        if (Status != ApplicationStatus.UnderReview)
            return Result.Failure(LoanErrors.NotUnderReview);

        if (score.Value < 650)
            return Result.Failure(LoanErrors.CreditScoreTooLow);

        if (ratio.Value > 0.43m)
            return Result.Failure(LoanErrors.DebtRatioTooHigh);

        Status = ApplicationStatus.Approved;
        RaiseDomainEvent(new LoanApprovedDomainEvent(Id, Amount));

        return Result.Success();
    }
}

Long-Lived Projects

Projects expected to last years benefit from clean boundaries. Requirements change, frameworks evolve, team members rotate. Clean Architecture makes the codebase resilient to these changes.

If the project has a 6-month lifespan and will be replaced, the investment doesn't pay off.

Multiple Teams

When multiple teams work on the same codebase, clear boundaries prevent them from stepping on each other. The Domain layer is the stable core everyone agrees on.

High Testability Requirements

If comprehensive testing is a hard requirement (regulated industries, financial systems, healthcare), Clean Architecture makes the domain layer trivially testable - no mocks for databases or HTTP needed.

I've written more about why Clean Architecture is great for complex projects if you recognize your project in these signals.

When to Skip Clean Architecture

Simple CRUD Applications

If your application is mostly reading and writing data with minimal business logic:

// This doesn't need Clean Architecture
app.MapPost("/api/todos", async (TodoRequest request, AppDbContext db) =>
{
    var todo = new Todo { Title = request.Title, IsComplete = false };
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($"/api/todos/{todo.Id}", todo);
});

For CRUD, a single project with Minimal APIs and EF Core is faster to build, easier to understand, and perfectly maintainable.

Prototypes and MVPs

Speed matters more than architecture when you're validating an idea. Build the simplest thing that works. Refactor into Clean Architecture later if the project survives.

Small Microservices

A microservice with a narrow responsibility (send emails, resize images, generate PDFs) doesn't need four projects and a domain model. Keep it simple.

Internal Tools

Admin dashboards, migration scripts, and one-off data tools don't justify the ceremony. Ship fast, iterate, replace.

The Decision Framework

A decision tree: a complex, long-lived, multi-team, high-testability project points to Clean Architecture, a CRUD, MVP, or small-service project points to keeping it simple, and mixed answers point to starting simple and migrating later

Ask these questions.

Questions where "yes" points to Clean Architecture:

  • Does the domain have complex business rules?
  • Will the project live for 2+ years?
  • Do multiple teams contribute to the same codebase?
  • Is testability a hard requirement (regulated industry, financial, healthcare)?

Questions where "yes" points to a simpler structure:

  • Is it mostly CRUD?
  • Is it a prototype or MVP?
  • Is it a small, focused microservice?
  • Is it an internal tool you'd rather replace than maintain?

If you answer "yes" to most of the first group, Clean Architecture is a good fit. If you answer "yes" to most of the second group, keep it simple. Mixed answers usually mean: start simple, and let the migration path below carry you.

Alternatives to Clean Architecture

Vertical Slice Architecture

Vertical Slice Architecture organizes code by feature instead of by layer. Each feature contains everything it needs - from request to response.

Best for: Medium-complexity applications where features are independent and don't share much domain logic. I compare the two approaches head-to-head in Vertical Slice Architecture vs Clean Architecture.

Simple Layered Architecture

The classic three-layer approach: Presentation → Business → Data. Less ceremony than Clean Architecture, still provides some separation.

Best for: Applications with moderate complexity that don't need the full rigor of Clean Architecture.

Single Project

Everything in one project, organized by feature folders.

Best for: Small applications, prototypes, microservices, and internal tools.

The Migration Path

You don't have to start with Clean Architecture. Start simple and evolve:

  1. Start: Single project with feature folders
  2. Grow: Extract a Domain project when business logic appears
  3. Mature: Add Application and Infrastructure projects when needed
  4. Scale: Add architecture tests to enforce boundaries

This is cheaper than starting with four empty projects and hoping you'll need them.

Common Objections

"But what if we need Clean Architecture later?" You'll know. When business logic starts leaking into controllers or database code infects your domain, it's time. Refactoring from a well-organized simple project to Clean Architecture is straightforward.

"Clean Architecture is industry standard." It's one approach among many. Hexagonal Architecture, Vertical Slices, and even well-structured monoliths are all valid. Choose based on your specific needs.

"My team expects Clean Architecture." Make the decision based on the project, not on habits. If the team knows Clean Architecture well and the project benefits from it, great. If it's adding overhead, question it.

The Bottom Line

Clean Architecture is a tool, not a dogma. Use it when your domain is complex, the project is long-lived, and testability matters. Skip it when simplicity serves you better.

The best architecture is the one that makes your team productive and your software maintainable - whatever that looks like for your specific project.

Thanks for reading, and stay awesome!


Frequently Asked Questions

When should you use Clean Architecture?

When the domain has complex business rules, the project will live for years, multiple teams share the codebase, or testability is a hard requirement. Those are the problems the architecture actually solves.

Is Clean Architecture overkill for CRUD applications?

Usually yes. If the application mostly reads and writes data with minimal business logic, a single well-organized project with Minimal APIs and EF Core is faster to build and just as maintainable.

Can you migrate to Clean Architecture later?

Yes, and it is often the better path. Start with a single project organized by feature, extract a Domain project when real business logic appears, then add Application and Infrastructure projects as needed.

What are the alternatives to Clean Architecture?

Vertical Slice Architecture organizes code by feature instead of by layer. A simple three-layer architecture offers lighter separation. And a single project with feature folders is fine for small apps, prototypes, and focused microservices.

Does Clean Architecture slow down development?

It adds upfront cost: more projects, more abstractions, more mapping. On complex, long-lived systems that cost pays for itself in testability and changeability. On simple projects it is pure overhead.

Loading comments...

Whenever you're ready, there are 4 ways I can help you:

  1. Pragmatic Clean Architecture: Join 5,000+ students in this comprehensive course that will teach you the system I use to ship production-ready applications using Clean Architecture. Learn how to apply the best practices of modern software architecture.
  2. Modular Monolith Architecture: Join 2,800+ engineers in this in-depth course that will transform the way you build modern systems. You will learn the best practices for applying the Modular Monolith architecture in a real-world scenario.
  3. Pragmatic REST APIs: Join 1,900+ students in this course that will teach you how to build production-ready REST APIs using the latest ASP.NET Core features and best practices. It includes a fully functional UI application that we'll integrate with the REST API.
  4. Patreon Community: Join a community of 5,000+ engineers and software architects. You will also unlock access to the source code I use in my YouTube videos, early access to future videos, and exclusive discounts for my courses.

The .NET Weekly

Become a Better .NET Software Engineer

Join 66,000+ engineers who are improving their skills every Saturday morning.