Skip to content
bitzorcas
中EN

Guide

Ten Architecture Anti-Patterns & Operational Pitfalls

Senior architect guide to avoiding production catastrophes: dissecting async deadlocks, module layer leaks, tenant isolation breaches, and unverified AI mutation loops.

Last updated

Ten Architecture Anti-Patterns & Operational Pitfalls

An exceptional framework baseline defines not only what developers should do, but explicitly codifies what is strictly forbidden. During fast-paced feature development, subtle architectural smells can easily compromise system resilience, trigger thread pool starvation, or cause disastrous multi-tenant data leaks.

Authored from a senior full-stack architect’s perspective, this runbook details 10 fatal architectural anti-patterns and their corresponding defensive principles.


1. Sync-over-Async Thread Pool Starvation

  • Fatal Anti-Pattern: Calling .Result or .Wait() on asynchronous tasks inside Mediator pipeline behaviors or command handlers:
    // Strictly forbidden: easily exhausts ASP.NET Core thread pools under load
    var user = _userRepository.GetByIdAsync(userId).Result;
    • Defensive Invariant: Implement end-to-end async/await passing CancellationToken through every layer to the underlying storage driver.

2. Cross-Module Layer Penetration

  • Fatal Anti-Pattern: Referencing Identity.Infrastructure or Identity.Domain directly in Litigation.Application.csproj.
    • Defensive Invariant: Modules reference only *.Contracts of other modules at compile time. Cross-module communication uses CAP transactional outbox events or read-only store interfaces declared in Contracts. This invariant is enforced by automated ArchitectureTests.

3. Multi-Tenant Cache & Raw SQL Leakage

  • Fatal Anti-Pattern: Omitting TenantId in Dapper queries or caching tenant-scoped data in a global Redis key:
    // Strictly forbidden: Tenant A reads Tenant B cached summaries
    await _cache.SetAsync("active_case_summary", summary);
    • Defensive Invariant: Prefix all cache keys with tenant namespaces (e.g., $"tenant:{tenantId}:cases:{caseId}"). Every raw SQL query must explicitly include TenantId = @TenantId in its WHERE clause.

4. Local Clock Table Partition Drift

  • Fatal Anti-Pattern: Calling DateTime.Now inside table partitioning routines. When deployed inside container hosts with differing host clocks, daily partitions drift across time zones.
    • Defensive Invariant: Standardize entirely on UTC (DateTimeOffset.UtcNow). Time zone conversions are presentation-layer responsibilities only.

5. DTO Proliferation in Simple CRUD

  • Productivity Anti-Pattern: Hand-crafting 15 separate single-use DTOs and AutoMapper mappings for a three-column lookup table.
    • Defensive Invariant: Follow the framework’s isomorphic aggregate principle. Internal vertical slices reuse strongly typed aggregate roots directly; external DTOs are defined only when traversing physical network boundaries.

6. Blocking Outbound Calls in Long Transactions

  • Distributed Anti-Pattern: Invoking external payment gateways or third-party judicial APIs directly inside a relational database transaction block, holding row locks for seconds.
    • Defensive Invariant: Commit database transactions rapidly. Write outbound intentions to the transactional Outbox (CAP), allowing asynchronous background workers to handle network retries.

7. Throwing Raw Exceptions for Business Logic

  • Error Handling Anti-Pattern: Throwing throw new Exception("Insufficient balance") to convey routine business rejection.
    • Defensive Invariant: Business rejections are not crashes; return strongly typed Result.Failure(ModuleErrors.Code). Reserve exceptions strictly for physical failures (e.g., network partitions), handled globally via RFC 9457 ProblemDetails.

8. Magic String Pollution

  • Maintainability Anti-Pattern: Littering application logic with arbitrary strings such as "PENDING", "01", or "ERR_FAIL".
    • Defensive Invariant: Declare all status codes as enums or smart enums; declare error codes in static readonly *Errors catalogs for global searchability.

9. Live Migration Table-Locking Index Drops

  • Operational Anti-Pattern: Running DROP INDEX and recreating indexes on multi-million-row production tables during live deployments.
    • Defensive Invariant: BitzOrcas catalog probing prohibits dropping indexes on existing tables. Only missing tables and columns (ALTER TABLE ADD NULL with LOCK_TIMEOUT 5000) are modified during live rollout.

10. Unsupervised Autonomous Agent Mutations

  • AI Governance Anti-Pattern: Permitting autonomous models to execute irreversible payouts, deletions, or contract revocations without human confirmation.
    • Defensive Invariant: High-risk mutations enforce Human-in-the-Loop (HITL) via the Prepare & Confirm pattern, requiring human operator MFA Step-Up confirmation before execution.

100%

Scroll or use controls to zoom · drag when enlarged · double-click for 100% / 200%