Clean Architecture Folder Structure in .NET: A Simple Guide
Learn how to organise a .NET solution with Clean Architecture. Understand the Domain, Application, Infrastructure, and Presentation layers, the dependency rule, and the exact folders, with diagrams and examples.
A building with the vault at the centre
Think about how a bank building is designed. Right at the centre is the vault, holding the most precious thing — the money and the core rules about it. Around the vault are the staff areas, where employees follow procedures to serve customers. Further out are the service desks and machines that connect to the outside world. And at the very outside is the public entrance, where customers walk in.
Notice the direction of importance. The outer areas depend on and protect the inner ones. The vault does not depend on the front door — but the front door's whole purpose is to safely reach the vault. You could change the entrance, repaint the lobby, or swap the ATMs, and the vault and its rules stay untouched.
Clean Architecture organises your code the same way. Your most precious thing — the business rules — sits safe in the centre, knowing nothing about databases, web frameworks, or screens. The outer layers depend inward toward it, never the reverse. Change your database or your web framework, and your core business logic does not even notice.
Let us learn the four layers, the one golden rule, and exactly which folders go where.
The four layers
Clean Architecture has four layers, arranged from the inside out. Each is usually a separate .NET project.
- Domain — the centre. Entities, value objects, aggregates, domain events, and the rules that are always true. It references nothing else.
- Application — the use cases. It orchestrates the domain to do real tasks ("place an order", "register a user"), often using CQRS commands and queries. It depends only on the Domain.
- Infrastructure — the outside-facing implementations: EF Core, the database, message brokers, email, file storage. It implements interfaces defined inside.
- Presentation — the entry point, usually a Web API with controllers or minimal API endpoints. It receives requests and calls the Application.
The one golden rule: dependencies point inward
If you remember only one thing about Clean Architecture, remember this: source code dependencies only point inward.
The Dependency Rule
Steps
Domain
Depends on NOTHING — pure business rules
Application
Depends only on Domain
Infrastructure
Depends on Domain + Application (implements their interfaces)
Presentation
Depends on Application; wires everything at startup
This is what makes the architecture "clean." Your business rules (Domain) do not know whether you use SQL Server or PostgreSQL, ASP.NET Core or something else. Those are details on the outside. You can swap them without touching the core.
A quick test: open your Domain project and look at its references. If it references EF Core, ASP.NET Core, or any database package — the rule is broken. The Domain should reference nothing but plain .NET.
The folder structure, layer by layer
Here is a typical solution. Each layer is a project, and inside each project the folders group related things.
MySolution/
├── src/
│ ├── MyApp.Domain/ // the core — references nothing
│ │ ├── Orders/
│ │ │ ├── Order.cs // entity / aggregate root
│ │ │ ├── OrderItem.cs // entity
│ │ │ ├── OrderStatus.cs // value object / enum
│ │ │ └── IOrderRepository.cs // interface (abstraction)
│ │ ├── Customers/
│ │ └── Common/ // base classes, domain events
│ │
│ ├── MyApp.Application/ // use cases — references Domain
│ │ ├── Orders/
│ │ │ ├── PlaceOrder/
│ │ │ │ ├── PlaceOrderCommand.cs
│ │ │ │ └── PlaceOrderHandler.cs
│ │ │ └── GetOrder/
│ │ ├── Common/
│ │ │ └── IEmailService.cs // interface the app needs
│ │ └── DependencyInjection.cs
│ │
│ ├── MyApp.Infrastructure/ // implementations — references Domain + Application
│ │ ├── Persistence/
│ │ │ ├── AppDbContext.cs
│ │ │ └── OrderRepository.cs // implements IOrderRepository
│ │ ├── Services/
│ │ │ └── EmailService.cs // implements IEmailService
│ │ └── DependencyInjection.cs
│ │
│ └── MyApp.Api/ // entry point — references Application (+ Infra at startup)
│ ├── Endpoints/
│ │ └── OrderEndpoints.cs
│ ├── Middleware/
│ └── Program.csRead the comments next to each project — they show exactly what each layer is allowed to reference. This is the dependency rule made real.
The clever trick: Dependency Inversion
Here is a puzzle. The Application needs to save orders to a database. But saving to a database is Infrastructure, which is an outer layer. If the Application depended on Infrastructure, the arrows would point outward — breaking the rule. How do we solve this?
The answer is the Dependency Inversion Principle. The inner layer defines an interface for what it needs, and the outer layer provides the implementation.
In code:
// In Domain (or Application) — the inner layer says WHAT it needs
public interface IOrderRepository
{
Task Add(Order order, CancellationToken ct);
Task<Order?> GetById(int id, CancellationToken ct);
}
// In Infrastructure — the outer layer says HOW it is done
public class OrderRepository(AppDbContext db) : IOrderRepository
{
public async Task Add(Order order, CancellationToken ct) =>
await db.Orders.AddAsync(order, ct);
public async Task<Order?> GetById(int id, CancellationToken ct) =>
await db.Orders.FindAsync([id], ct);
}The Application uses IOrderRepository and never knows EF Core exists. Infrastructure provides the real thing. The arrow points inward, and the rule holds.
Wiring it together at startup
The layers stay separate, but someone must connect them. That job belongs to the Presentation project at startup (the "composition root"). It is the only place allowed to know about every layer:
// Program.cs in MyApp.Api
builder.Services.AddApplication(); // from MyApp.Application
builder.Services.AddInfrastructure(builder.Configuration); // from MyApp.Infrastructure
var app = builder.Build();
app.MapOrderEndpoints();
app.Run();Each layer exposes a small AddXxx() method that registers its own services. The API just calls them. This keeps each layer's wiring inside that layer, and the API stays clean.
A request's journey through the layers
When a request arrives, it travels inward through the layers and back out:
Where does each thing go?
A common beginner question is "which folder does this belong in?" This table answers the most frequent ones:
| Thing | Layer | Why |
|---|---|---|
Entity / aggregate (Order) | Domain | It is core business data with rules |
Value object (Money, Email) | Domain | Pure, rule-carrying values |
| Repository interface | Domain / Application | The core says what it needs |
Use case / handler (PlaceOrder) | Application | Orchestrates the domain |
| DTO / request / response | Application | Shapes data for a use case |
| Repository implementation | Infrastructure | EF Core detail |
DbContext, email sender | Infrastructure | External-facing detail |
| Controller / endpoint | Presentation | The entry point |
Program.cs, DI wiring | Presentation | The composition root |
A simple rule decides most cases: if it is a business rule, it goes inward (Domain/Application); if it talks to the outside world (database, network, files), it goes outward (Infrastructure/Presentation).
Why this structure makes testing easy
One of the biggest payoffs of Clean Architecture is testability. Because the Domain and Application depend on nothing concrete, you can test all your business rules without a database, a web server, or any framework.
Testing Each Layer
Steps
Domain
Pure unit tests — no DB, instant, test the rules
Application
Test use cases with fake repositories (in-memory)
Infrastructure
Integration tests against a real test database
End-to-end
Full HTTP tests through the API for key flows
Because the core defines interfaces, your Application tests can pass a simple fake repository instead of a real database. The tests run in milliseconds, and they test business behaviour, not plumbing. This speed and focus is hard to get when business rules are tangled up with EF Core and controllers.
Clean Architecture vs simple layering
| Simple N-layer | Clean Architecture | |
|---|---|---|
| Dependency direction | Often top-to-bottom (UI → DB) | Always inward (toward Domain) |
| Business rules depend on DB? | Often yes | No — fully independent |
| Swap the database easily? | Hard | Easy |
| Best for | Small, simple apps | Complex, long-lived business apps |
The big difference is where the database sits. In old-style layering, the database is at the bottom and everything depends on it. In Clean Architecture, the database is an outer detail, and the business rules sit safely at the centre, depending on nothing.
When to use Clean Architecture
Clean Architecture is a great fit for:
- Complex business apps with rich rules that will live and grow for years.
- Teams that want clear boundaries and testable business logic.
- Projects where the database or framework might change, and you want the core protected.
It can be overkill for:
- Tiny apps, prototypes, or simple CRUD where the ceremony of four projects adds more friction than value. There, simple layering or vertical slices may be lighter.
Clean Architecture and Vertical Slice Architecture are not enemies. A popular combination keeps Clean Architecture's project layers and dependency rule, while organising the Application layer by feature slices. You get strong boundaries and feature-first code together.
Quick recap
- Clean Architecture has four layers: Domain (core rules), Application (use cases), Infrastructure (database and services), and Presentation (Web API).
- The golden rule: source code dependencies point inward. The Domain depends on nothing.
- Dependency Inversion lets the inner layers define interfaces that outer layers implement, so the database stays an outer detail.
- Each layer is usually its own project, so the compiler enforces the rule; the Presentation project wires everything at startup.
- Use it for complex, long-lived apps; for tiny CRUD apps, lighter structures may serve better.
Keep your business rules in the vault at the centre, let the outer layers depend inward to protect them, and you get a codebase where the important logic stays clean, testable, and safe from every change happening on the outside. Start with the four projects, respect the one golden rule, and let each layer reference only the ones inside it. Once that habit is in place, your application can grow for years — swapping databases, frameworks, and UIs along the way — while the heart of your software stays calm and untouched at the centre.
References and further reading
- Common web application architectures — Microsoft Learn — Microsoft's official overview, including Clean Architecture.
- How To Approach Clean Architecture Folder Structure — Milan Jovanović — a popular, detailed .NET guide.
- Clean Architecture boilerplate — Microsoft ISE Developer Blog — a real-world reference structure.
Related Posts
Clean Architecture in .NET: The Benefits of Structured Software Design
A beginner-friendly guide to Clean Architecture in .NET. Learn the four layers, the dependency rule, and why structured software design keeps your code easy to change.
Vertical Slice Architecture in .NET: The Easy Guide
Learn Vertical Slice Architecture in .NET in simple words. Organise code by feature instead of by layer, with diagrams, real examples, a comparison with Clean Architecture, and when to use each.
What Is a Modular Monolith? A Beginner-Friendly Guide for .NET
Understand the modular monolith in simple words: one app, strong internal walls. Learn how it compares to monoliths and microservices, why it is the 2026 default for most .NET teams, and how to build one.
Clean Architecture: The Missing Chapter Most Tutorials Skip
The missing chapter of Clean Architecture in .NET: where code really goes, what the dependency rule means, and the pragmatic choices tutorials skip.
Screaming Architecture in .NET: Let Your Folders Tell the Story
Learn Screaming Architecture in .NET in plain words. Make your folder structure shout the business purpose, not the framework, with diagrams and real examples.
The Best Way to Structure .NET Projects: Clean Architecture + Vertical Slices
A friendly guide to structuring .NET projects by mixing Clean Architecture with Vertical Slices, with diagrams, code, tables, and simple, beginner-ready advice.