132 published guides

Explore the library

Browse The .NET Weekly archive →
  • Clean Architecture

    Background Jobs in Clean Architecture

    Where do background jobs fit in Clean Architecture? Treat them as entry points, exactly like controllers. The job schedules and triggers, the application layer does the work. Here is the structure, the scoped-service wiring that trips everyone up, and complete examples with BackgroundService and Quartz.

  • Clean Architecture

    Clean Architecture With Minimal APIs in .NET

    Minimal API endpoints and Clean Architecture are a natural fit: the endpoint receives HTTP, dispatches a command, and maps the result back. No business logic, no controllers, no ceremony. Here is how to organize endpoints by feature, validate with endpoint filters, and return consistent Problem Details.

  • Clean Architecture

    Dependency Rule in Clean Architecture Explained

    Source code dependencies must only point inward. That one sentence decides your project references, where your interfaces live, and why the DI container sits at the edge. Here is how the Dependency Rule works, how control can flow outward while dependencies point inward, and how to enforce it with the compiler and architecture tests.

  • Clean Architecture

    Domain Events vs Integration Events in .NET

    A domain event is handled in-process, inside the same transaction. An integration event crosses service boundaries through a message broker and needs the outbox pattern to survive a crash. Confusing the two leads to lost events and accidental coupling. Here is where the line sits, with implementation patterns for both sides.

  • Clean Architecture

    Exception Handling Strategy in Clean Architecture

    Expected failures are not exceptional, so stop throwing them. A clear strategy gives each layer one job: the domain throws on invariant violations, the application returns typed Results, and a single global handler maps everything else to Problem Details. Here is how the pieces fit together in a .NET Clean Architecture.

  • Clean Architecture

    How to Organize Use Cases in Clean Architecture

    A folder structure that works at 5 use cases falls apart at 200. Group by feature, keep one use case per folder, and name with verb-noun domain language, and your Application layer reads like a list of things the system can do. Here are the three layouts you will encounter, and why only one of them scales.

  • Clean Architecture

    Logging Strategy in Clean Architecture

    One pipeline behavior can log every use case with timing and failures, so handlers stay clean and the domain never sees an ILogger. Here is a layer-by-layer logging strategy for Clean Architecture: domain events instead of logs in the domain, behaviors in the application, direct logging in infrastructure, and middleware at the edge.

  • Clean Architecture

    Mapping Between Layers in Clean Architecture

    Request to command, command to entity, entity to response: a single operation can pass through three mappings, and most of them are ceremony. EF Core projections eliminate the read-side mapping entirely, and simple extension methods handle the rest. Here is when mapping between layers earns its keep, and why you rarely need AutoMapper.

  • Clean Architecture

    The Application Layer in Clean Architecture

    The Application layer is where your use cases live: commands, queries, and the handlers that orchestrate your domain objects. A good handler reads like a table of contents (load, act, save). Here is how to structure the layer in .NET and keep business logic from leaking into it.

  • Clean Architecture

    The Domain Layer in Clean Architecture

    Every business rule in your system should have exactly one home: the Domain layer. That means entities that guard their invariants, value objects instead of raw primitives, and domain events for side effects. Here is what belongs in the Domain layer, what does not, and how to keep it at zero external dependencies.

  • Clean Architecture

    The Infrastructure Layer in Clean Architecture

    Databases, message brokers, email providers, caches: everything that talks to the outside world lives in the Infrastructure layer. It implements the interfaces your inner layers define, and it is the only place EF Core should ever appear. Here is how to structure it in .NET, from repositories and the DbContext to a clean DI registration module.

  • Clean Architecture

    When to Use Clean Architecture (And When Not To)

    A five-endpoint CRUD API with four projects, domain events, and a CQRS pipeline is over-engineering, not discipline. Clean Architecture pays off on complex domains, long-lived codebases, and multi-team projects. Here is a decision framework for spotting which one you have, and a migration path for when you guess wrong.

Domain-Driven Design

  • Domain-Driven Design

    Aggregate Design in DDD - Rules, Boundaries, and Consistency

    Aggregates are the most important tactical pattern in Domain-Driven Design. They define consistency boundaries, enforce invariants, and protect your domain model. Here are the rules and practical guidance for designing aggregates in .NET.

  • Domain-Driven Design

    Anti-Corruption Layer in Domain-Driven Design

    An Anti-Corruption Layer prevents external systems from polluting your domain model. It translates between your clean domain language and the messy reality of legacy systems or third-party APIs.

  • Domain-Driven Design

    Application Services vs Domain Services in DDD

    Application services coordinate use cases. Domain services hold business rules that do not fit one entity or value object. These .NET examples show where loading, transactions, and decisions belong, including the edge cases around repositories and concurrency.

  • Domain-Driven Design

    Context Mapping in DDD: Relationships Between Bounded Contexts

    Conformist, partnership, customer-supplier: context mapping patterns are not diagram decorations. They are power dynamics that predict which team absorbs breaking changes. Here is each pattern, when it happens to you, and what it looks like in .NET code.

  • Domain-Driven Design

    Domain Services in DDD: When and How to Use Them

    Domain Services handle business logic that does not naturally belong to a single entity or value object. Here is when to use them, how to implement them in .NET, and how they differ from Application Services.

  • Domain-Driven Design

    EventStorming for .NET Teams: A Practical Guide

    EventStorming brings domain experts and developers together to explore a business process through events. Use the timeline to expose missing rules, investigate possible bounded contexts, and choose which behaviors to model in .NET.

  • Domain-Driven Design

    How to Model Value Objects With EF Core

    Value objects have no identity - they are defined by their properties. EF Core gives you three ways to persist them: owned types, complex types, and value conversions. Here is when to use each.

  • Domain-Driven Design

    Persistence Ignorance With EF Core: How Close Can You Get?

    EF Core can persist rich domain models without public setters or mapping attributes. Private constructors, backing fields, and external configuration keep database concerns out of business methods. Here are the mappings and the compromises they still require.

  • Domain-Driven Design

    Process Manager vs Saga: What's the Difference?

    A saga coordinates local transactions and recovery across services. A process manager tracks workflow state and decides the next step. They often work together: the process manager orchestrates the saga and its compensations.

  • Domain-Driven Design

    Rich Domain Model vs Anemic Domain Model in C#

    An anemic domain model separates data from behavior. A rich domain model keeps them together. Here is why it matters, how to refactor from anemic to rich, and when each approach is appropriate.

  • Domain-Driven Design

    Specification Pattern in C# With EF Core

    The Specification pattern encapsulates query logic into reusable objects. Combined with EF Core, it eliminates query duplication and keeps your repositories clean. Here is how to implement it in C#.

  • Domain-Driven Design

    Strategic DDD vs Tactical DDD Explained

    Strategic DDD tells you where to draw boundaries. Tactical DDD tells you how to model within those boundaries. Most teams skip strategy and jump straight to tactics - and that is a mistake.

  • Domain-Driven Design

    Strongly Typed IDs in C# to Prevent Primitive Obsession

    Passing Guid parameters around is error-prone. Strongly typed IDs wrap primitives in domain-specific types so you cannot accidentally pass an OrderId where a CustomerId is expected. Here is how to implement them in C# with EF Core support.

  • Domain-Driven Design

    The Always-Valid Domain Model

    An always-valid domain model enforces business invariants at construction and on every state change. Private constructors, validated value objects, and guarded methods reduce repeated validation while keeping persistence and concurrency checks explicit.

  • Domain-Driven Design

    Transaction Script vs Domain Model Pattern

    A transaction script puts a use case in one procedure; a domain model puts business rules inside domain objects. Compare equivalent C# order-pricing examples, the testing tradeoffs, and a gradual path from scripts to a richer model.

  • Domain-Driven Design

    Ubiquitous Language in Domain-Driven Design

    Ubiquitous language puts the same business terms in conversations, code, and tests. Use precise operation names, respect differences between bounded contexts, and refine the vocabulary as the model evolves.

  • Domain-Driven Design

    Bounded Context in DDD Explained With Examples

    Bounded contexts let Ordering and Fulfillment use different models of the same concepts. Define those boundaries in .NET, translate integration contracts, and keep ownership of models and data explicit.

Databases

  • Databases

    Distributed Locking With Postgres Advisory Locks in .NET

    You probably do not need Redis, RedLock, or ZooKeeper for distributed locking. If your instances already share a Postgres database, they share a lock manager too. Session-level advisory locks serialize work across every instance and auto-release the moment a holder dies, which is the exact property TTL-based leases spend fencing tokens trying to approximate.

  • Databases

    Why Postgres Ignores Your Index (Sargability, Taught by a Kata)

    Your query is correct, your tests pass, and the index you carefully created is never touched. The usual culprit is one innocent-looking habit: wrapping the column in a function. Here is what sargability means, how to catch the problem with EXPLAIN, and how I built a coding kata that grades your query plan so the lesson actually sticks.

  • Databases

    Dapper in .NET: A Practical Guide

    Dapper's value proposition is predictability: the SQL you write is the SQL that runs, with object mapping and nothing else. This guide covers the patterns you need in a real application: queries, parameters, multi-mapping, QueryMultiple, transactions, and where Dapper fits next to EF Core.

Caching

  • Caching

    Content-Addressed Caching in .NET: Cache Keys That Never Go Stale

    Cache invalidation is hard because we name cache entries after locations. Name them after a hash of their inputs instead, and the whole class of stale-read bugs stops being possible: change any input, get a different key, recompute under it. Git, Docker, and NuGet all run on this idea, and it works just as well inside your own application.

  • Caching

    Multi-Level Caching in .NET With FusionCache

    Rolling your own IMemoryCache plus Redis gets you 80% of a caching stack and silently skips the three hard parts: cross-instance invalidation, cache stampede, and serving stale data when the source is down. FusionCache gives you L1, L2, a backplane, and all three behaviors out of the box.

Messaging

  • Messaging

    How I Use NATS JetStream as a Job Queue in .NET

    My first job queue was a Redis list, and it had two ways to silently lose a job: a worker crash after LPOP, and a broker restart. NATS JetStream closed both with a work-queue stream, a durable pull consumer, and one ordering rule: publish the result before you ack the job. Here is the whole design, small enough to read in five minutes.

  • Messaging

    RabbitMQ vs Kafka for .NET Applications

    RabbitMQ deletes messages once consumed; Kafka keeps them and moves a cursor. That single design decision explains almost every difference between them: replay, fan-out, ordering, routing, and scaling. Understand it and the choice for your .NET system mostly makes itself.

Observability

  • Observability

    OpenTelemetry Collectors: The Agent + Gateway Pattern

    One OpenTelemetry Collector is easy. The interesting design shows up the moment your apps run on more than one machine: a small agent collector on every box, forwarding to one gateway collector that fans out to Tempo, Loki, and Prometheus. Here is the two-tier setup I run in production, including the two config lines that stop the collector from OOM-killing the box it shares with real workloads.

Testing

  • Testing

    Architecture Fitness Functions in .NET With ArchUnitNET

    An architecture rule nobody enforces is a wish with a code-review lottery attached. A fitness function turns it into a build failure that names the offending type. Here is how to write them with ArchUnitNET, including slice cycle detection, the three ways a fitness function quietly lies to you, and what to do when your rule set outgrows code.

  • Testing

    Unit Testing Best Practices in .NET

    Unit tests should be fast, reliable, and maintainable. But poorly written tests become a burden that slows development. Here are the best practices for writing effective unit tests in .NET.

AI for .NET

  • AI for .NET

    Building a RAG System in .NET

    Every RAG demo works until you point it at your own documents and it confidently makes things up. The model is rarely the problem. Chunking, embeddings, and retrieval quality decide whether the answer comes from your data or from thin air. Here is a complete RAG pipeline in .NET with Microsoft.Extensions.AI, PostgreSQL with pgvector, hybrid search, re-ranking, and source attribution.

API Design

  • API Design

    Choosing the Right HTTP Status Codes for Your API

    Nobody argues about 200 and 500. The fights are in the middle: 400 vs 422, 401 vs 403, 404 vs 410, and whether 200-with-an-error-body is ever acceptable (it is not). A decision tree for the ambiguous cases, with the ASP.NET Core mappings to make it stick.

ASP.NET Core

  • ASP.NET Core

    Minimal APIs in .NET: Complete Guide

    Minimal APIs are a lightweight way to build HTTP APIs in .NET without controllers, startup classes, or conventions. Here is a complete guide covering routing, validation, authentication, and structuring Minimal APIs at scale.

C#

DevOps

Distributed Systems

  • Distributed Systems

    Saga Pattern in .NET: Managing Distributed Transactions

    The Saga pattern manages distributed transactions across multiple services by breaking them into local transactions with compensating actions. Here is how to implement both orchestration and choreography sagas in .NET.

Microservices

  • Microservices

    Microservices in .NET: Getting Started Guide

    A .NET microservice system needs more than separately deployed APIs: each service owns its data, communication survives partial failure, and traces cross every boundary. This guide builds a small end-to-end system and makes the cost visible before you choose it.

Performance

  • Performance

    Async/Await Performance Pitfalls in .NET

    Async improves throughput only while the work stays nonblocking. Sync-over-async, accidental serialization, unnecessary state machines, and unbounded fan-out can make an asynchronous endpoint slower or deadlock it entirely.

real time

Resilience

  • Resilience

    Polly v8: Resilience Pipelines Explained

    Polly v8 replaced policies with resilience pipelines: a rewritten core with allocation-free execution, built-in telemetry, and one composition model instead of PolicyWrap. Here is how the new API maps to the old one, how to register pipelines with DI, and why the order you add strategies changes what your pipeline actually does.

Security