Microservices Anti‑Patterns

1) Distributed Monolith

What: Many “services” but tightly coupled (shared releases, schemas, libraries).
Why: Changes ripple across services; no independent deploys.
Better: Independent deployability as a gate; per‑service DB; contract tests; semantic versioning.

2) Shared Database

What: Multiple services read/write the same DB/tables.
Why: Hidden coupling, unsafe joins, brittle migrations.
Better: Database‑per‑service, expose data via APIs/events; use read projections if you need joins.

3) Nano‑Services (Over‑fragmentation)

What: Too many tiny services (one method = one service).
Why: Chatty calls, high ops cost, complex debugging.
Better: Size by bounded context/capability; merge services until cohesion > coupling.

4) Chatty, Synchronous Chains

What: Long request chains (A→B→C→D) for one user call.
Why: Latency amplification; cascading failures.
Better: Coarse‑grained APIs, aggregation at BFF/gateway, async messaging for non‑critical work, cache.

5) Dual Writes Without a Saga

What: Service updates two stores in one request with no coordination.
Why: Partial writes, data drift.
Better: Saga pattern (orchestration/choreography), outbox + CDC, idempotent handlers.

6) 2PC Across Services

What: Distributed XA/2‑phase commit for cross‑service ACID.
Why: Fragile, slow, vendor lock‑in.
Better: Eventual consistency with Sagas; compensating actions; user‑visible states.

7) Wrong Service Boundaries

What: Split by technical layers (controllers vs DAOs) instead of domain.
Why: High cross‑service chatter, unclear ownership.
Better: Decompose by business capability/subdomain; use DDD and anti‑corruption layers.

8) God Service / Central Orchestrator for Everything

What: One service coordinates most flows.
Why: Becomes a bottleneck and single point of failure.
Better: Balance orchestration vs choreography; push logic to owning services; enforce boundaries.

9) Shared “Core” Libraries for Domain Logic

What: Multiple services depend on the same internal domain jar.
Why: Tight coupling; version pinning across fleet.
Better: Share only pure utilities; share domain via API/Events, not code.

10) Bypassing the Gateway

What: Clients call random services directly.
Why: Leaky topology, inconsistent auth/rate limits, breaking changes hit clients.
Better: API gateway/BFF, consistent auth, throttling, routing, schema/contract governance.

11) No Resilience (Retries/Timeouts/Circuit Breakers)

What: Blind HTTP calls with default timeouts.
Why: Cascading outages, resource exhaustion.
Better: Timeouts, bounded retries with jitter, circuit breakers, bulkheads, fallbacks.

12) Snowflake Deployments

What: Manual deploys and hand‑crafted servers.
Why: Drift, irreproducible incidents, slow recovery.
Better: CI/CD, immutable images, IaC (Terraform), blue‑green/rolling canaries.

13) Missing Observability

What: Logs only; no correlation, metrics, or traces.
Why: Slow MTTR; guessing during incidents.
Better: Structured logs + trace IDs, OpenTelemetry traces, RED/Golden metrics, SLOs/alerts.

14) Environment Parity Gaps

What: Dev/stage/prod differ (ports, configs, data).
Why: “Works on my machine” bugs.
Better: Containerized dev; prod‑like dependencies locally; config via env/secret managers.

15) Centralized Team Owning Every Service

What: Platform team changes app code; feature teams blocked.
Why: Bottlenecks, slow delivery.
Better: You build it, you run it; clear ownership, paved roads from a platform team.

16) Overusing Events for Simple CRUD

What: Everything becomes async/event‑sourced.
Why: Hidden flows, hard debugging, eventual‑consistency surprises.
Better: Use events where they add value; keep simple CRUD synchronous behind clear APIs.

17) Fat DTOs / Leaky Contracts

What: Expose internal models directly.
Why: Breaks clients on change; over‑fetch/under‑fetch.
Better: Versioned, purpose‑built contracts; GraphQL/BFFs for client shaping.

18) No Idempotency

What: Retries create duplicates or corrupt state.
Why: At‑least‑once delivery becomes dangerous.
Better: Idempotency keys, upserts, natural/business keys, dedupe guards.

19) Single Store for All Workloads

What: One DB forced to serve OLTP + analytics + search.
Why: Contention, bad performance.
Better: Polyglot persistence with projections; CQRS where justified.

20) Premature Microservices

What: Split too early without domain clarity.
Why: Complexity before benefits.
Better: Start as a modular monolith; extract services when boundaries are stable.


Quick checklist to stay sane

  • Independent deploys? ✅
  • Per‑service data ownership? ✅
  • Contracts & versioning? ✅
  • Resilience + observability baked in? ✅
  • CI/CD + IaC + environment parity? ✅

Want this as a one‑page PDF/playbook for your team? I can whip that up.

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.