FBT P
⌘K
β–Έ Backend Master Reference

BACKEND DEVELOPMENTCOMPLETE REFERENCE

Every principle, pattern, standard, and approach you need to build production-grade backend systems in .NET, Python, and Rust β€” structured, searchable, and FBT-grade.

21SECTIONS
80+PATTERNS
3LANGUAGES
∞POSSIBILITIES
.NETPythonRustClean ArchitectureCQRSDDDMicroservicesEvent-Driven
⚑

Design Principles

14 items
AcronymFull NameWhatWhyWhen
SSingle Responsibility PrincipleA class should have only one reason to change. Each module should be responsible for a single user, actor, or role.Improves maintainability, testability, and modularity. Reduces coupling and makes code changes less risky.When designing class responsibilities and determining where to place business logic.
OOpen/Closed PrincipleSoftware entities should be open for extension but closed for modification. Add new behavior through extension, not by changing existing code.Reduces risk of breaking existing functionality when adding new features. Encourages flexible design.When you need to add new features without touching stable code. Use interfaces and inheritance.
LLiskov Substitution PrincipleDerived classes must be substitutable for their base classes without breaking the contract. Objects of derived classes should work seamlessly where base class objects are expected.Ensures type safety and prevents unexpected runtime errors. Enables polymorphism to work correctly.When designing inheritance hierarchies and interface implementations. Check that subtypes honor parent contracts.
IInterface Segregation PrincipleClients should not be forced to depend on interfaces they do not use. Prefer many small, specific interfaces over large, general ones.Reduces coupling between components. Clients only depend on what they actually need.When defining interfaces and abstract contracts. Split large interfaces into smaller, focused ones.
DDependency Inversion PrincipleHigh-level modules should not depend on low-level modules; both should depend on abstractions. Depend on abstractions, not concrete implementations.Decouples layers and components. Makes testing easier through mocking and dependency injection.When organizing application architecture. Use DI containers to manage dependencies.
DRYDon't Repeat YourselfEvery piece of knowledge should have a single, unambiguous representation in the system. Avoid duplicating logic, data, or intent.Reduces bugs by centralizing logic. Changes only need to happen in one place. Improves maintainability.When writing code, refactor duplication into reusable functions, classes, or utilities.
KISSKeep It Simple, StupidDesign and implement using the simplest approach that solves the problem. Avoid unnecessary complexity, abstraction, or sophistication.Simpler code is easier to understand, debug, and maintain. Reduces cognitive load.During design and implementation. Choose straightforward solutions before considering complex alternatives.
YAGNIYou Aren't Gonna Need ItDo not add functionality until it is explicitly required. Avoid speculative development of features "just in case."Reduces code bloat and maintenance burden. Keeps the codebase lean and focused.When tempted to add "future-proofing" features. Build only what is needed now.
SoCSeparation of ConcernsDivide the program into distinct sections, each handling a specific concern or responsibility. Different parts should manage different aspects (UI, business logic, data access).Improves modularity, testability, and reusability. Makes code easier to understand and modify.In overall application architecture. Separate presentation, business logic, and data persistence layers.
LoDLaw of DemeterAn object should only communicate with its direct dependencies, not with the dependencies of its dependencies. Avoid chained method calls like obj.a().b().c().Reduces coupling and brittleness. Changes to intermediate objects don't break callers.When designing object interactions and method interfaces. Keep call chains shallow.
CQSCommand Query SeparationMethods should either perform an action (Command) or return data (Query), not both. Separate methods that modify state from those that retrieve state.Improves clarity and predictability. Easier to reason about side effects. Enables better caching and optimization.When designing public interfaces and APIs. Use distinct methods for reading and writing.
CoCConvention over ConfigurationProvide sensible defaults and follow established conventions rather than requiring explicit configuration for common scenarios.Reduces boilerplate and setup time. Makes projects more consistent and easier to navigate.When designing frameworks and libraries. Establish conventions that developers can rely on.
PIEProgram to Interfaces, not ImplementationsCode against abstract interfaces rather than concrete implementations. This enables loose coupling and polymorphism.Makes code more flexible and testable. Allows swapping implementations without changing client code.When designing dependencies and contracts. Use interfaces for external dependencies.
PoLAPrinciple of Least AstonishmentDesign systems so they behave as users expect. Avoid surprising behavior or unintuitive naming. Be consistent with similar components.Reduces cognitive load and errors. Makes code more predictable and easier to use.When designing APIs, naming conventions, and behavior. Consider developer expectations.
πŸ“

Coding Standards

6 items
#
C# Naming Conventions
csharp

Follow PascalCase for public members and camelCase for private fields. Use clear, descriptive names that express intent.

csharp
public class OrderProcessor
{
  private List _orders; // camelCase
  public void ProcessOrder(Order order) { } // PascalCase
  private bool ValidatePayment(Payment payment) { }
}
.NET
🐍
Python PEP 8 Style
python

Use snake_case for variables and functions, UPPER_CASE for constants. 4-space indentation. Max line length 79 chars (PEP 8) or 88 (Black).

python
def process_order(order: Order) -> bool:
    TIMEOUT_SECONDS = 30
    valid_items = validate_items(order.items)
    return valid_items and order.total > 0
Python
πŸ¦€
Rust Naming Conventions
rust

Use snake_case for variables, functions, and modules. PascalCase for types and constants. Follow Rust API guidelines for clarity.

rust
pub struct OrderProcessor {
    active_orders: Vec,
}

pub fn process_order(order: Order) -> Result<(), Error> {
    let ORDER_LIMIT = 1000;
    Ok(())
}
Rust
πŸ“¦
C# File Structure & Organization
csharp

One public class per file. Organize members: public methods, properties, private methods. Use namespaces to organize by feature or domain.

csharp
namespace Domain.Orders
{
  public class Order
  {
    public int Id { get; set; }
    public List Items { get; set; }
    
    public decimal GetTotal() => Items.Sum(i => i.Price);
    private void ValidateItems() { }
  }
}
.NET
πŸ“‚
Python Project Layout
text

Standard structure: src/package_name for code, tests/ for tests, setup.py/pyproject.toml for config. Use __init__.py for packages.

text
project/
β”œβ”€β”€ src/myapp/
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ models.py
β”‚   └── services.py
β”œβ”€β”€ tests/
β”‚   └── test_models.py
β”œβ”€β”€ pyproject.toml
└── README.md
Python
πŸ”§
Rust Workspace Organization
toml

Use workspaces for multi-crate projects. Separate library crates from binary crates. Clear module hierarchy with mod.rs.

toml
[workspace]
members = ["crates/api", "crates/domain"]

// src/lib.rs
pub mod domain;
pub mod services;

// domain/mod.rs
pub struct Order { }
pub mod validators;
Rust
🎯

Paradigms

6 items
πŸ—οΈ
Object-Oriented Programming

Organize code around objects with state and behavior. Emphasizes encapsulation, inheritance, and polymorphism. Natural for modeling real-world entities.

all
Ξ»
Functional Programming

Treat computation as the evaluation of pure functions. Emphasizes immutability, higher-order functions, and avoiding side effects. Easier reasoning and testing.

all
βš›οΈ
Reactive Programming

Build responsive systems using observable streams and event-driven architecture. Components react to data changes. Good for handling async operations.

all
πŸ“‹
Procedural Programming

Organize code as a sequence of procedures/functions that modify state. Direct control flow. Good for straightforward, step-by-step logic.

all
πŸ“
Declarative Programming

Specify what you want rather than how to achieve it. Let the system figure out the steps. Examples: SQL, configuration-based systems.

all
πŸ‘€
Actor Model

Concurrent systems based on independent actors communicating via messages. Avoids shared state and race conditions. Excellent for distributed systems.

all
πŸ›οΈ

Architectural Patterns

8 items
🎯
Clean Architecture

Concentric layers separating concerns: Entities, Use Cases, Interface Adapters, Frameworks. Dependencies point inward. Highly testable and decoupled.

Layers4
πŸ”·
Hexagonal Architecture

Ports and Adapters. Core business logic at center with external dependencies as adapters. Enables multiple entry/exit points without changing core logic.

SynonymsPorts & Adapters
πŸ”—
Microservices

Independently deployable services built around business capabilities. Each service has its own database. Scaled and developed independently. Increased complexity.

CommunicationAsync/REST/gRPC
πŸ“¦
Modular Monolith

Single deployment unit with clear module boundaries. Modules communicate through well-defined interfaces. Balances simplicity of monolith with organization of microservices.

ComplexityMedium
🏘️
Domain-Driven Design

Align software structure with business domain. Use ubiquitous language shared between developers and domain experts. Organize around bounded contexts.

FocusBusiness Value
⚑
Event-Driven Architecture

Components communicate through events. Decoupled producers and consumers. Excellent for real-time systems and maintaining eventual consistency across services.

PatternPub/Sub
🌐
Service-Oriented Architecture

Business capabilities exposed as reusable services. Heavy use of messaging and protocols. Enterprise-level approach, often with ESB and SOAP.

ProtocolSOAP/REST
☁️
Serverless Architecture

Run code without managing servers. Scale automatically. Pay per execution. Good for event-driven workloads and variable traffic patterns.

ScalingAutomatic
🎨

Design Patterns

22 items
πŸ”¨Creational PatternsObject creation mechanisms
Singleton
Creational
Ensure a class has only one instance and provide a global point of access to it. Use for loggers, configuration managers, connection pools.
When you need exactly one instance shared globally. Be careful of threading issues.
Factory Method
Creational
Define an interface for creating objects, letting subclasses decide which class to instantiate. Reduces coupling to concrete classes.
When object creation logic is complex or depends on runtime conditions.
Abstract Factory
Creational
Provide an interface for creating families of related objects. Ensures consistency across a set of related products.
When you need to create related object families (e.g., UI elements for different themes).
Builder
Creational
Separate construction of complex objects from their representation. Build objects step by step. Improves readability for objects with many parameters.
When constructing complex objects with many optional parameters or validation requirements.
Prototype
Creational
Specify kinds of objects to create using a prototype instance, cloning it rather than creating from scratch. Efficient for expensive object creation.
When object creation is expensive or when you need deep copies.
Object Pool
Creational
Reuse objects that are expensive to create by pooling them. Acquire from pool, use, return. Reduces allocation overhead.
When object creation is expensive and instances are used briefly then released.
πŸ—οΈStructural PatternsObject composition and relationships
Adapter
Structural
Convert the interface of a class into another interface clients expect. Bridge incompatible interfaces. Also called Wrapper.
When integrating third-party libraries or legacy code with incompatible interfaces.
Decorator
Structural
Attach additional responsibilities to an object dynamically, extending functionality without modifying the object. Flexible alternative to subclassing.
When you need to add behavior to individual objects without affecting others or creating new subclasses.
Proxy
Structural
Provide a surrogate or placeholder for another object to control access to it. Can add lazy loading, logging, or access control.
When you need to control access, defer creation, or add cross-cutting concerns.
Facade
Structural
Provide a unified, simplified interface to a set of interfaces in a subsystem. Hides complexity and reduces coupling.
When you want to simplify complex subsystems or provide a simpler API.
Composite
Structural
Compose objects into tree structures representing part-whole hierarchies. Clients treat individual objects and compositions uniformly.
When building tree structures (e.g., menu systems, document hierarchies).
Bridge
Structural
Decouple an abstraction from its implementation so they can vary independently. Avoid cartesian product of abstractions Γ— implementations.
When you have multiple dimensions of variation and want to avoid explosion of subclasses.
βš™οΈBehavioral PatternsObject collaboration and responsibility distribution
Strategy
Behavioral
Define a family of algorithms, encapsulate each one, and make them interchangeable. Clients can select strategies at runtime.
When you have multiple algorithms for a task and need to switch between them.
Observer
Behavioral
Define a one-to-many dependency so when one object changes state, all dependents are notified automatically. Implements publish-subscribe.
When you need loose coupling between components that must react to state changes.
Command
Behavioral
Encapsulate a request as an object, allowing you to parameterize clients with different requests, queue requests, and log/undo operations.
When you need undo/redo, queuing, or command logging.
Chain of Responsibility
Behavioral
Avoid coupling the sender of a request to its receiver by giving multiple objects a chance to handle it. Pass request along a chain.
When processing logic depends on runtime conditions or should be extensible.
Mediator
Behavioral
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly.
When multiple objects need to communicate in complex ways and you want to centralize that logic.
State
Behavioral
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
When an object's behavior depends on state and you have many conditional branches.
Template Method
Behavioral
Define the skeleton of an algorithm in a base class, letting subclasses fill in specific steps. Inverts control of algorithm steps.
When you have an algorithm with varying implementations of certain steps.
Visitor
Behavioral
Represent an operation to be performed on elements of an object structure. Lets you define new operations without changing the classes of those elements.
When you need to perform operations on complex object structures and operations change frequently.
Iterator
Behavioral
Provide a way to access elements of a collection sequentially without exposing its underlying representation.
When you need to traverse collections in various ways without exposing their internal structure.
Memento
Behavioral
Capture and externalize an object's internal state without violating encapsulation, and restore the object to this state later.
When you need to implement undo functionality or save/restore object state.
🏒

Enterprise Patterns

6 items
πŸ“¦
Repository Pattern
csharp

Abstract data access logic behind a repository interface. Clients interact with repositories instead of directly accessing data. Enables switching persistence mechanisms.

csharp
public interface IOrderRepository {
  Task GetByIdAsync(int id);
  Task> GetAllAsync();
  Task SaveAsync(Order order);
}

public class OrderRepository : IOrderRepository {
  private readonly DbContext _db;
  public Task GetByIdAsync(int id) => _db.Orders.FindAsync(id);
}
πŸ”„
Unit of Work Pattern
csharp

Maintain a collection of objects affected by a business transaction and coordinates writing changes and handling concurrency. Ensures all changes are atomic.

csharp
public interface IUnitOfWork {
  IOrderRepository Orders { get; }
  ICustomerRepository Customers { get; }
  Task SaveChangesAsync();
}

var order = await _uow.Orders.GetByIdAsync(1);
order.Status = OrderStatus.Shipped;
await _uow.SaveChangesAsync();
🎯
Specification Pattern
csharp

Encapsulate query logic in reusable specification objects. Separate complex filtering rules from repositories. Makes queries composable and testable.

csharp
public class ActiveOrdersSpec : Specification {
  public ActiveOrdersSpec() {
    AddCriteria(o => o.Status == OrderStatus.Active);
    AddInclude(o => o.Items);
  }
}

var orders = await repo.GetAsync(new ActiveOrdersSpec());
βš”οΈ
Anti-Corruption Layer
csharp

Create a layer that translates between external system contracts and your domain model. Isolates domain from changes in external systems.

csharp
public class LegacyOrderAdapter {
  public Order AdaptFromLegacy(LegacyOrderDto dto) {
    return new Order {
      Id = dto.OrderId,
      Status = MapLegacyStatus(dto.Status),
      Items = dto.Items.Select(AdaptItem).ToList()
    };
  }
}
πŸ“Š
Read Models

Maintain denormalized, query-optimized views of data separate from write models. Each read model is optimized for specific queries. Common in CQRS.

PatternCQRS
⏰
Sagas & Process Managers

Coordinate long-running, distributed transactions across multiple services. Sagas are event-driven; Process Managers route messages. Handle compensating transactions for failures.

ScopeDistributed
πŸ’Ύ

Data Handling

6 items
πŸ—„οΈ
Object-Relational Mapping (ORM)

Map objects to database tables. Handle hydration and persistence automatically. Examples: Entity Framework, SQLAlchemy, SeaORM. Trade flexibility for convenience.

Entity FrameworkSQLAlchemySeaORM
⚑
Query Builders & Micro-ORMs
csharp

Write SQL with less boilerplate through fluent APIs. Dapper, Linq2Db (C#), SQLAlchemy Core (Python), sqlx (Rust). More control than ORMs, less verbose than raw SQL.

csharp
var orders = await connection.QueryAsync(
  "SELECT * FROM Orders WHERE CustomerId = @CustomerId",
  new { CustomerId = 123 }
);
Dappersqlx
πŸ“œ
Database Migrations
csharp

Version control your schema changes. Migrations are versioned scripts or code that evolve schema over time. Reversible and trackable. Examples: Flyway, EF Migrations, Alembic.

csharp
public class AddOrderTableMigration : Migration {
  public override void Up() {
    CreateTable("Orders")
      .WithColumn("Id").AsInt32().PrimaryKey()
      .WithColumn("CustomerId").AsInt32()
      .WithColumn("Total").AsDecimal();
  }
}
βš™οΈ
Caching Strategies

Reduce database hits with in-memory or distributed caches. Cache-aside, write-through, write-behind patterns. Know cache invalidation strategies.

ComplexityHigh
πŸ“Š
Read Models

Denormalized views optimized for specific queries. Kept in sync with write model via events. Critical for read-heavy workloads and analytics.

πŸ”
Search Indexing

Full-text search and analytics via Elasticsearch, Solr, or similar. Index documents for fast, flexible querying beyond SQL capabilities.

ToolsElasticsearch, Meilisearch
πŸ“€

CQRS & Event Sourcing

6 items
1️⃣
HTTP Request

Client sends a command or query to the API endpoint.

2️⃣
Controller/Handler

Receives request, validates input, routes to command/query handler.

3️⃣
Pipeline/Middleware

Cross-cutting concerns: logging, validation, authorization, error handling.

4️⃣
Aggregate

Processes command, validates business rules, emits domain events. Single source of truth.

5️⃣
Outbox/Event Store

Persists events transactionally. Ensures no loss. Published asynchronously via message broker.

6️⃣
Projections

Subscribe to events, build denormalized read models for fast queries.

πŸ’‘Event Sourcing Example: Instead of storing final state, store sequence of events (OrderCreated, PaymentProcessed, OrderShipped). Rebuild state by replaying events.
πŸ—„οΈ

Database Patterns

10 items
πŸ”—
Database per Service

Each microservice owns its database schema. Enables independent scaling and schema evolution. Requires eventual consistency across services.

ScopeMicroservices
πŸ“Š
Shared Database

Multiple services share a database schema. Simpler to query across services but tight coupling. Hard to scale independently.

ScopeMonolith
πŸ‘₯
Multi-Tenancy

Serve multiple tenants in a single database. Shared or separate schemas. Requires careful data isolation and querying. Cost-effective but complex.

πŸ”„
Read Replicas

Replicate data to read-only copies for scaling read workloads. Asynchronous replication. Introduces eventual consistency window.

🎯
Sharding

Partition data across multiple database instances by a shard key (e.g., customer_id). Horizontal scaling for write-heavy workloads.

➑️
CQRS Split Database

Separate read and write databases. Writes go to normalized write DB, reads from optimized read DB. Projections keep them in sync.

πŸ“‘
Change Data Capture (CDC)

Capture database changes as a stream of events. Trigger downstream processes, update caches, replicate to other systems.

πŸ—‘οΈ
Soft Deletes

Mark records as deleted with a timestamp rather than removing them. Preserves history and allows recovery. Add filter to queries.

⏰
Temporal Tables

Database-native versioning. Track row changes over time. Queries can see historical versions. Available in SQL Server, PostgreSQL.

πŸ”’
Optimistic Concurrency

Use version numbers or timestamps instead of locks. Last writer wins after checking version hasn't changed. Good for distributed systems.

🌐

API Patterns

6 items
πŸ“
REST (Representational State Transfer)
text

Resource-oriented APIs using HTTP verbs (GET, POST, PUT, DELETE). Stateless, cacheable, standardized. Most common pattern. Status codes indicate outcome.

text
POST /api/orders
GET /api/orders/123
PUT /api/orders/123
DELETE /api/orders/123
πŸ”·
GraphQL
graphql

Query language for APIs. Clients request exact data needed, avoiding over-fetching. Strong typing, introspection, aggregates data from multiple sources.

graphql
query {
  order(id: 123) {
    id
    customer { name email }
    items { sku quantity }
  }
}
⚑
gRPC

High-performance RPC using HTTP/2 and Protocol Buffers. Typed contracts, streaming, multiplexing. Excellent for service-to-service communication.

Protocol
πŸ“‘
WebSockets & SSE

Real-time bidirectional (WebSocket) or server-to-client (SSE) communication. Avoid polling. Good for notifications and live updates.

πŸš€
Minimal APIs

Light-weight, convention-free API definition. Map HTTP endpoints directly to handler functions. Less ceremony than controllers. Common in .NET 6+.

.NET
πŸšͺ
API Gateway

Single entry point for clients. Routes requests, handles authentication, rate limiting, response transformation. Decouples clients from backend services.

πŸ’¬

Messaging & Events

9 items
πŸ“’
Pub/Sub (Publish/Subscribe)

Publishers send messages to a topic; subscribers receive copies. Decouples producers from consumers. Examples: Azure Service Bus Topics, AWS SNS, RabbitMQ Topic Exchange.

πŸ“¦
Message Queue

FIFO delivery of messages to a queue. Single consumer per message. Guarantees order and delivery. Examples: Azure Queue Storage, RabbitMQ Queues, SQS.

⚑
Event Streaming

Append-only log of events. Consumers read from any offset. Replay-able history. Examples: Kafka, Pulsar, Azure Event Hubs.

DeliveryAt-Least-Once
⚠️
Dead Letter Queue (DLQ)

Messages that fail processing multiple times are moved to a DLQ for investigation. Prevents poison pill messages from blocking queue.

πŸ‘₯
Competing Consumers

Multiple instances consume from same queue in parallel. Each message processed once. Scale processing by adding consumers.

πŸ”„
Request-Reply Pattern

Sender publishes request on a queue, receiver processes and replies on reply queue. Synchronous semantics over async transport.

πŸ“Ž
Claim Check Pattern

Large message payload moved to blob storage; message contains reference/claim check. Reduces message size and bus load.

πŸ’ƒ
Choreography

Services communicate directly via events. Each service knows what events trigger its actions. Distributed decision-making. Can get tangled.

🎼
Orchestration

Central orchestrator/saga manager directs the flow. Services do not know about each other. Clearer flow but central point of failure.

βš™οΈ

Concurrency

6 items
⏳
Async/Await
csharp

Non-blocking operations that free up threads while waiting. Efficient use of thread pool. Syntactically simple with async/await keywords. Standard pattern.

csharp
public async Task GetOrderAsync(int id) {
  var order = await _db.Orders.FindAsync(id);
  var items = await _db.OrderItems
    .Where(i => i.OrderId == id)
    .ToListAsync();
  return order;
}
πŸ”’
Mutex/Lock/Semaphore

Mutual exclusion for accessing shared resources. Mutex (binary), Lock (reentrant), Semaphore (count). Risk of deadlock. Use sparingly in async code.

πŸš‡
Channels

Thread-safe communication between concurrent tasks/goroutines. Producer-consumer pattern. Typed, built-in cancellation. Rust: mpsc channels, C#: System.Threading.Channels.

⚑
Thread Pool / Task Parallel

Automatically manage thread creation and reuse. Task Parallel Library (C#) coordinates work. Avoids manual thread creation and context switching overhead.

🎯
Single-Flight/Deduplication

Coalesce multiple identical concurrent requests into a single operation. Return same result to all requesters. Avoid thundering herd.

πŸ¦€
Rust Ownership & Borrowing

Compile-time concurrency safety. Ownership rules prevent data races. Move vs borrow semantics. No need for locks on immutable shared data.

Rust
πŸ§ͺ

Testing

8 items
πŸ“
Unit Tests

Test individual functions/methods in isolation with mocks. Fast, fine-grained feedback. Cover happy paths and edge cases.

Pyramid70%
πŸ”—
Integration Tests

Test components working together (database, external services). Use test doubles or in-memory databases. Slower but more realistic.

Pyramid20%
πŸ“‹
Contract Tests

Verify API contracts between services without full E2E testing. Consumer-driven contracts. Catch integration issues early.

🎲
Property-Based Tests

Generate random inputs and verify invariants hold. Examples: QuickCheck, Hypothesis. Find edge cases you didn't think of.

πŸ“Έ
Snapshot Tests

Capture output (JSON, HTML) and verify against stored snapshots. Good for UI, configuration, complex data structures.

πŸ›οΈ
Architecture Tests

Verify code structure adheres to design rules. ArchUnit (Java), NArchitecture (C#). Enforce layering, dependencies, naming conventions.

πŸ“Š
Load/Performance Tests

Simulate realistic load. Measure throughput, latency, resource usage. Find bottlenecks. Examples: K6, JMeter, Apache Bench.

🧬
Mutation Testing

Inject small code changes and verify tests catch them. Low mutation score indicates insufficient test coverage.

πŸ”ΊTesting Pyramid: 70% unit tests, 20% integration tests, 10% E2E. Many fast unit tests, fewer slow E2E tests.
❌

Error Handling

4 items
πŸ“¦
Result/Either Type
rust

Return Result<T, E> or Either<L, R> instead of throwing exceptions. Explicit error handling. Composable with map/flatMap. Rust Result, Scala Either.

rust
pub fn process_order(order: Order) -> Result {
  let payment = process_payment(&order)?;
  let confirmation = create_confirmation(&order, &payment)?;
  Ok(confirmation)
}
πŸ—οΈ
Exception Hierarchy
csharp

Create domain-specific exception classes inheriting from base. Catch specific exceptions. Avoid catching generic Exception.

csharp
public class OrderException : Exception { }
public class InsufficientFundsException : OrderException { }
public class ItemOutOfStockException : OrderException { }
πŸ”„
Retry with Backoff
csharp

Exponential or fixed backoff for transient failures. Jitter to avoid thundering herd. Max retries to avoid infinite loops. Use Polly (C#), tenacity (Python).

csharp
var policy = Policy
  .Handle()
  .WaitAndRetry(new[] {
    TimeSpan.FromSeconds(1),
    TimeSpan.FromSeconds(2),
    TimeSpan.FromSeconds(4)
  });
await policy.ExecuteAsync(() => client.GetAsync(url));
⚑
Circuit Breaker

Prevent cascading failures by stopping requests to failing service. Open β†’ Half-Open β†’ Closed states. Polly, Hystrix, or cloud SDK.

πŸ”

Security

12 items
πŸ”‘
OAuth 2.0 & OpenID Connect

Delegate authentication to identity provider. OAuth 2.0 for authorization, OIDC adds identity. Authorization Code flow for web, PKCE for SPAs.

StandardRFC 6749
🎫
JWT + Refresh Tokens

Stateless authentication with JWTs. Short-lived access tokens + long-lived refresh tokens. No session storage needed. Verify signature server-side.

πŸ‘₯
RBAC & ABAC

Role-Based (RBAC) or Attribute-Based (ABAC) access control. RBAC: users have roles with permissions. ABAC: fine-grained rules on user/resource attributes.

πŸ”“
API Key Authentication

Simple token-based auth for service-to-service or public APIs. Stateless, easy to revoke. Send in header or query. Less secure than OAuth.

βœ”οΈ
Input Validation

Validate all input at API boundaries. Type, length, format, range. Use libraries like FluentValidation (C#), Pydantic (Python). Prevent injection attacks.

πŸ›‘οΈ
Parameterized Queries

Use parameterized statements to prevent SQL injection. Never concatenate user input into SQL. All major ORMs and drivers support this.

πŸ”’
Secrets Management

Store secrets (API keys, passwords, connection strings) in secure vaults, not code. Azure Key Vault, AWS Secrets Manager, HashiCorp Vault.

🌐
CORS (Cross-Origin Resource Sharing)

Control which origins can access API. Specify allowed origins, methods, headers. Prevents unauthorized cross-site requests.

⏱️
Rate Limiting

Limit requests per IP/user/key to prevent abuse and DoS. Use token bucket or sliding window algorithm. Return 429 Too Many Requests.

πŸ”—
Zero Trust

Never trust, always verify. Authenticate and authorize every request/connection. Encrypt in transit and at rest. Assume breach mentality.

πŸ”„
Idempotency

API operations should be safe to retry. Use idempotency keys to prevent duplicate processing. Critical for payment systems.

πŸ“
Audit Logging

Log all security events: authentication, authorization, data access, changes. Immutable logs for compliance and investigation.

πŸ”

Observability

5 items
πŸ“‹
Structured Logging
json

Log as JSON with consistent fields (timestamp, level, trace-id, user-id, message). Query and aggregate logs by field. Tools: ELK, Loki, CloudWatch.

json
{
  "timestamp": "2024-01-15T10:30:00Z",
  "level": "INFO",
  "trace_id": "abc123",
  "user_id": 456,
  "message": "Order created",
  "order_id": 789
}
πŸ“Š
Metrics

Quantitative measurements: request rate, latency, error rate, queue depth. Emit via Prometheus, Datadog, or cloud provider. Alert on thresholds.

πŸ”—
Distributed Tracing

Track request flow across services using trace and span IDs. Visualize latency bottlenecks. Tools: Jaeger, Zipkin, Datadog APM.

❀️
Health Checks

Expose /health endpoint returning service health status. Check dependencies (database, cache). Used for load balancing and orchestration.

🚨
Alerting

Set up alerts on metrics, logs, and traces. Alert on anomalies and thresholds. Route to on-call via PagerDuty, OpsGenie, etc.

⚑

Performance

6 items
πŸ’Ύ
Caching

In-memory (Redis, Memcached), application-level, HTTP caching. Cache-aside pattern. Set appropriate TTLs. Handle invalidation carefully.

πŸ“„
Pagination

Return large result sets in pages. Cursor-based pagination scales better than offset. Include total count carefully (can be expensive).

πŸ“¦
Batch Processing

Group operations to reduce round trips. Bulk insert/update queries. Batch message publishing. Trade latency for throughput.

πŸ”‘
Database Indexing

Add indexes on frequently queried columns. Watch N+1 queries. Analyze query plans. Composite indexes for multi-column filters.

⚑
Async Everything

Use async I/O for network calls, file access, database queries. Free up threads. Apply backpressure to avoid overload.

πŸ”—
Connection Pooling

Reuse database/HTTP connections via pools. Reduce connection overhead. Configure pool size based on workload.

πŸš€

Deployment

8 items
πŸ”΅πŸŸ’
Blue/Green Deployment

Run two identical production environments. Switch traffic from blue to green. Zero downtime. Instant rollback by switching back.

🐀
Canary Deployment

Gradually shift traffic to new version. Start with 5%, monitor, increase to 50%, then 100%. Catch issues with partial rollout.

🚩
Feature Flags

Toggle features on/off at runtime without redeploy. A/B test, gradual rollout, kill switches. LaunchDarkly, Unleash, or custom.

πŸ”„
Rolling Deployment

Gradually replace old instances with new version. Requires load balancer and health checks. Brief period with mixed versions.

❄️
Immutable Infrastructure

Build versioned machine images (AMI, Docker image). Deploy by replacing entire instances, never modify in-place. Reproducible and reliable.

πŸ”€
GitOps

Git repo as source of truth for infrastructure and applications. Declarative config, automated sync. Tools: ArgoCD, Flux.

πŸšͺ
Health Gates

Automated checks before deployment: tests pass, security scan clears, performance benchmarks acceptable. Prevent bad deployments.

πŸ”§
Migration Safety

Plan schema changes to work with both old and new code. Deploy code before schema or vice versa. Use feature flags to control behavior.

#

.NET/C# Specific

6 items
πŸ”—
Dependency Injection
csharp

Built-in DI container in .NET. Register services with IServiceCollection. Constructor injection. Transient, scoped, singleton lifetimes.

csharp
services.AddScoped();
services.AddSingleton();
services.AddTransient();
.NET
πŸ”€
Middleware Pipeline
csharp

Request flows through middleware components. Each adds behavior (logging, auth, error handling). Order matters. Use app.Use() to add custom middleware.

csharp
app.UseAuthentication();
app.UseAuthorization();
app.UseCustomErrorHandling();
app.MapControllers();
βœ”οΈ
FluentValidation
csharp

Fluent API for defining validation rules. Separate validators from models. Composable, reusable, testable. Integrates with Minimal APIs.

csharp
public class CreateOrderValidator : AbstractValidator {
  public CreateOrderValidator() {
    RuleFor(x => x.CustomerId).NotEmpty();
    RuleFor(x => x.Items).NotEmpty().WithMessage("Must have items");
  }
}
.NET
πŸ—ΊοΈ
AutoMapper & Mapster

Convention-based object mapping. DTO ↔ Domain models. Reduce boilerplate. Mapster is faster than AutoMapper.

.NET
⏰
Background Services

IHostedService for long-running tasks. Worker services run continuously. Scoped dependency injection for each iteration.

.NET
🎯
Vertical Slice Architecture

Organize by feature, not layer. Each feature has command, handler, validator, projections. Reduces cross-feature coupling.

ToolsMediatR, FastEndpoints
.NET
πŸ“šKey .NET libraries: Entity Framework Core (ORM), Dapper (Micro-ORM), MassTransit (Messaging), NUnit/xUnit (Testing), Serilog (Logging).
🐍

Python Specific

6 items
⚑
FastAPI
python

Modern, fast web framework for building APIs. Automatic OpenAPI/Swagger docs. Built on Starlette and Pydantic. Type hints drive validation and docs.

python
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Order(BaseModel):
    id: int
    total: float

@app.get("/orders/{order_id}")
async def get_order(order_id: int) -> Order:
    return Order(id=order_id, total=99.99)
Python
βœ”οΈ
Pydantic v2
python

Data validation and parsing using Python type hints. Automatic schema generation. Serialization/deserialization. Settings management.

python
from pydantic import BaseModel, Field, validator

class Order(BaseModel):
    id: int = Field(..., gt=0)
    total: float = Field(..., gt=0)
    
    @validator("total")
    def validate_total(cls, v):
        if v > 1000000:
            raise ValueError("Total too large")
        return v
Python
πŸ—„οΈ
SQLAlchemy 2.x

SQL toolkit and Object-Relational Mapper. Modern API with type hints. SQLAlchemy 2.0+ emphasizes async and explicit SQL.

Python
πŸ”—
Dependency Injection

Use dataclasses/Pydantic for DI. Dependency() in FastAPI for request scope. Or use libraries like python-dependency-injector.

Python
⏳
Async Patterns

asyncio for concurrency. async/await syntax. Asyncio.gather() for concurrent tasks. Event loops and tasks. Understanding asyncio is critical.

Python
πŸ“¦
Dataclasses & Protocols

dataclasses for lightweight data structures. Protocols (structural typing) for flexible interfaces. TypedDict for dict typing.

Python
πŸ“šKey Python ecosystem: pytest (Testing), sqlalchemy (ORM), httpx (HTTP client), uvicorn (ASGI server), black (Formatter), ruff (Linter).
πŸ¦€

Rust Specific

6 items
⚑
Tokio
rust

Async runtime for Rust. Tokio::spawn for tasks, channels for communication, select! for multiplexing. Production-grade for building servers.

rust
use tokio::task;

#[tokio::main]
async fn main() {
    let task1 = task::spawn(async { 1 + 1 });
    let result = task1.await.unwrap();
    println!("Result: {}", result);
}
Rust
🌐
Axum
rust

Modern, ergonomic web framework built on Tokio. Type-safe extractors. Clean routing DSL. Router composition. Built-in middleware.

rust
use axum::{routing::get, Router};

#[tokio::main]
async fn main() {
    let app = Router::new()
        .route("/orders/:id", get(get_order));
    
    axum::Server::bind(&"0.0.0.0:3000".parse()?)
        .serve(app.into_make_service())
        .await?
}
Rust
πŸ—„οΈ
sqlx & SeaORM

sqlx: compile-time checked SQL queries. SeaORM: async-first ORM. Both leverage Rust type system and async/await.

Rust
❌
Error Handling
rust

Result<T, E> type. Custom error enums. thiserror/anyhow crates for ergonomic error handling. Compile-time enforcement of error handling.

rust
pub fn process_order(order: Order) -> Result<(), OrderError> {
    validate_order(&order)?;
    let payment = charge_payment(&order)?;
    Ok(())
}
Rust
🎯
Trait-Based Design

Use traits for abstractions. Trait objects for dynamic dispatch. Blanket implementations for generics. Natural for DI and mocking.

Rust
πŸ“€
Serde

Serialize/deserialize Rust data structures to/from JSON, TOML, YAML, etc. Derive macros make it easy. Type-safe and performant.

Rust
πŸ“šKey Rust ecosystem: tokio (Async runtime), axum (Web framework), sqlx (Database), serde (Serialization), tracing (Logging), uuid (IDs).