132 published guides

Explore the library

Browse The .NET Weekly archive →

Domain-Driven Design

  • 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

    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

    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 generic. 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, which leaves well-modeled code inside the wrong boundaries.

  • 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 when the holder's connection closes. TTL-based leases approximate that with expiry times and fencing tokens.

  • Databases

    Dapper in .NET: A Practical Guide

    Dapper runs exactly the SQL you write and maps the results to objects, with nothing else in between. 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, because changing any input produces a different key. 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 but skips three hard problems: 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 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.

  • 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. Classify your messages as jobs or as facts and you know which one your .NET system needs.

Observability

  • Observability

    OpenTelemetry Collectors: The Agent + Gateway Pattern

    One OpenTelemetry Collector is easy. The design changes once 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 keep the collector's memory in check on the box it shares with real workloads.

Testing

  • Testing

    Architecture Fitness Functions in .NET With ArchUnitNET

    An architecture rule nobody enforces depends on reviewers catching every violation. 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, three ways a fitness function stays green while the code breaks the rule, and what to do when your rule set outgrows code.

  • Testing

    Unit Testing Best Practices in .NET

    Poorly written unit tests break on every refactor and slow development down. These .NET practices cover test structure, naming, test data builders, mocking boundaries, and testing behavior instead of implementation details.

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. 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.

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. This guide covers 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 does.

Security