Architectural Patterns#

Architectural patterns are proven structural templates for organizing software systems. Each pattern makes different tradeoffs between complexity, scalability, flexibility, and maintainability. Choosing the right one depends on your constraints and quality attributes.


Layered Architecture#

The most common pattern — organizes code into horizontal layers with strict dependency rules:

┌─────────────────────────────┐
│   Presentation Layer        │  UI, API endpoints
├─────────────────────────────┤
│   Business Logic Layer      │  Domain rules, workflows
├─────────────────────────────┤
│   Persistence Layer         │  Data access, repositories
├─────────────────────────────┤
│   Database Layer            │  Storage engines
└─────────────────────────────┘
     Dependencies flow DOWN only
AspectDetails
PrincipleEach layer only depends on the layer directly below
VariantsStrict (only adjacent layers) vs relaxed (skip layers)
StrengthsSimple, well-understood, good separation of concerns
WeaknessesMonolithic deployments, changes ripple through layers
Best forTraditional business applications, CRUD systems, small teams

Sinkhole Anti-Pattern#

When requests pass through layers without adding value — just forwarding calls. If > 20% of requests are sinkholes, the architecture is over-layered.


Pipe-and-Filter#

Data flows through a pipeline of independent processing stages:

Input → [Filter A] → [Filter B] → [Filter C] → Output
              │             │             │
         Transform      Validate       Enrich
AspectDetails
PrincipleEach filter transforms data independently; pipes connect them
StrengthsHighly composable, easy to add/remove/reorder stages
WeaknessesNot suited for interactive systems; overhead in serialization
Best forData processing, ETL, compilers, Unix command pipelines

Example: Data Pipeline#

Raw CSV → [Parse] → [Validate] → [Transform] → [Enrich] → [Load to DB]
                         │
                    [Error Queue]

Variants#

VariantDescription
Linear pipelineStrict sequential processing
Fork/joinParallel branches that merge
Feedback loopOutput routed back as input

Broker Pattern#

A central broker mediates communication between decoupled components:

┌──────────┐     ┌──────────┐     ┌──────────┐
│ Producer │────→│  Broker  │────→│ Consumer │
└──────────┘     │(mediator)│     └──────────┘
┌──────────┐     │          │     ┌──────────┐
│ Producer │────→│          │────→│ Consumer │
└──────────┘     └──────────┘     └──────────┘
AspectDetails
PrincipleProducers and consumers don’t know about each other
StrengthsLoose coupling, dynamic routing, protocol translation
WeaknessesBroker is SPOF, added latency, complexity
Best forMessage-oriented middleware, service buses, event systems

Implementations#

TechnologyTypeUse Case
RabbitMQMessage brokerTask queues, RPC
Apache KafkaEvent streamingEvent sourcing, CDC
AWS SNS/SQSCloud messagingServerless event-driven
Redis Pub/SubIn-memory brokerReal-time notifications

Peer-to-Peer#

All nodes are equal — each can be both client and server:

    ┌───┐     ┌───┐
    │ A │─────│ B │
    └─┬─┘     └─┬─┘
      │    ╲    │
      │     ╲   │
    ┌─┴─┐   ┌┴──┐
    │ C │───│ D │
    └───┘   └───┘
AspectDetails
PrincipleNo central authority; nodes discover and communicate directly
StrengthsFault-tolerant, scalable, no SPOF
WeaknessesComplex coordination, eventual consistency, discovery overhead
Best forFile sharing (BitTorrent), blockchain, distributed databases

P2P Variants#

VariantStructureExample
Pure P2PNo central node at allEarly Gnutella
Hybrid P2PSome supernodes for coordinationSkype (legacy), BitTorrent trackers
Structured P2PDeterministic topology (DHT)Chord, Kademlia, IPFS

Space-Based Architecture#

Designed for extreme scalability by eliminating the database as a bottleneck:

┌────────────────────────────────────────────────┐
│              Virtualized Middleware             │
│  ┌──────┐  ┌──────┐  ┌──────┐  ┌──────┐     │
│  │ PU 1 │  │ PU 2 │  │ PU 3 │  │ PU N │     │
│  │      │  │      │  │      │  │      │     │
│  │ App  │  │ App  │  │ App  │  │ App  │     │
│  │ Cache │  │ Cache │  │ Cache │  │ Cache │     │
│  └──────┘  └──────┘  └──────┘  └──────┘     │
│         ↕ Data Replication Grid ↕              │
├────────────────────────────────────────────────┤
│  Messaging Grid │ Data Grid │ Processing Grid  │
├────────────────────────────────────────────────┤
│         Async Database Write-Behind            │
│                    ┌────┐                      │
│                    │ DB │                      │
│                    └────┘                      │
└────────────────────────────────────────────────┘
AspectDetails
PrincipleProcessing units hold data in-memory; no shared DB for hot path
StrengthsNear-infinite scalability, low latency, handles spikes
WeaknessesComplex, eventual consistency, costly, hard to debug
Best forConcert ticketing, flash sales, real-time bidding, gaming

Key Components#

ComponentPurpose
Processing Unit (PU)Self-contained app + in-memory data grid
Data replicationSync state across PUs
Messaging gridRoute requests to PUs
Data pumpAsync write-behind to persistent store

Serverless Architecture#

Functions execute in response to events — no server management:

┌──────────┐     ┌───────────────┐     ┌──────────┐
│  Event   │────→│   Function    │────→│  Output  │
│ (trigger)│     │ (ephemeral)   │     │ (storage)│
└──────────┘     └───────────────┘     └──────────┘

Events: HTTP request, queue message, file upload, schedule
AspectDetails
PrincipleWrite functions; cloud handles scaling, availability, infrastructure
StrengthsZero ops, pay-per-use, auto-scaling, fast to deploy
WeaknessesCold starts, vendor lock-in, debugging difficulty, state management
Best forEvent-driven workloads, APIs, scheduled tasks, glue logic

Serverless Patterns#

PatternDescription
API backendAPI Gateway + Lambda + DynamoDB
Event processorS3/SQS trigger + Lambda + downstream
Scheduled jobEventBridge schedule + Lambda
ChoreographyEvents flow between functions via queues/topics

Limitations#

ConcernChallenge
Cold start100ms-several seconds on first invocation
DurationMax 15 minutes (AWS Lambda)
StateMust externalize to DB/cache/S3
TestingHard to replicate cloud environment locally
Vendor lock-inTight coupling to provider’s event model

Pattern Comparison#

PatternScalabilitySimplicityDeployabilityFault ToleranceCost
LayeredLowHighLow (monolith)LowLow
Pipe-and-FilterMediumMediumMediumMediumLow
BrokerHighMediumHighMedium (SPOF)Medium
Peer-to-PeerVery HighLowHighVery HighLow
Space-BasedVery HighLowHighHighHigh
ServerlessVery HighMediumVery HighHighVariable

Decision Matrix#

If you need…Consider
Simple CRUD applicationLayered
Data transformation pipelinePipe-and-Filter
Decoupled async communicationBroker
Extreme fault tolerance, no central pointPeer-to-Peer
Extreme scalability for burst trafficSpace-Based
Minimal ops, event-driven workloadsServerless
Independent team deploymentMicroservices (see previous chapter)

Combining Patterns#

Real systems combine patterns. A modern e-commerce platform might use:

  • Layered within each microservice
  • Broker (Kafka) between services
  • Serverless for event-driven background tasks
  • Pipe-and-filter for data ingestion
  • Space-based for the checkout during flash sales

The art is knowing which pattern solves which problem at which level of the system.


Key Takeaways#

  1. No pattern is universally best — each optimizes for different quality attributes.
  2. Layered architecture is the safe default for simple applications but resists scaling.
  3. Pipe-and-filter excels for data processing; think Unix philosophy.
  4. Broker decouples producers from consumers but introduces a SPOF.
  5. Space-based solves extreme scale but at extreme complexity and cost.
  6. Serverless minimizes operations but introduces cold starts and vendor lock-in.
  7. Real systems combine patterns at different levels — choose per component, not per system.