ARCHITECTURE IS A TRADEOFF

Choose the fit.
Understand the cost.

A CLI, a complex business application and independent services ask different things of their architecture. Change the scenario, compare the approaches, then read the lesson behind each choice.

These are editorial suitability ratings, not performance benchmarks, popularity statistics or a universal ranking. 1: usually avoid · 3: useful with a specific need · 5: strong starting choice. Styles can be combined.

17 approaches, sorted by suitability for small tool or cli.

Pipes and filters: data through independent stages

Compose transformations while making backpressure and errors explicit.

5/5Cost: Medium

Simple monolith: start with one executable

Keep a small application understandable without premature service boundaries.

5/5Cost: Low

Layered architecture: transport, application, storage

Separate responsibilities without confusing logical layers with deployed tiers.

3/5Cost: Medium

Microkernel: a small core with explicit extensions

Extend behavior through contracts without assuming dynamic shared libraries.

3/5Cost: High

Modular monolith: boundaries inside one deployment

Give business capabilities explicit APIs while retaining local transactions.

3/5Cost: Medium

Ports and adapters with a real request

Trace an HTTP adapter through an application operation to a storage port and compare test boundaries.

3/5Cost: Medium

Vertical slices: organize around a use case

Keep feature changes together without duplicating shared invariants.

3/5Cost: Medium

Clean and Onion: dependencies point toward policy

Keep domain policy independent of framework and database details.

2/5Cost: Medium to high

Web, queue, worker: make slow work durable

Separate request latency from background completion.

2/5Cost: High

BFF: an API shaped for one client

Compose client-specific views while retaining business ownership.

1/5Cost: High

CQRS: different models for commands and queries

Separate change rules from read shape without assuming two databases.

1/5Cost: Medium to high

DDD: bounded contexts and aggregates

Model language and invariants before choosing storage or transport.

1/5Cost: High

Event sourcing: state from a durable history

Distinguish a source of truth from ordinary logs and notifications.

1/5Cost: Very high

Event-driven services: delivery and idempotency

Treat duplicate delivery as normal and define the durable boundary.

1/5Cost: High

Microservices: pay for independent ownership

Extract a remote boundary only when its independence is valuable.

1/5Cost: Very high

Serverless handlers: bounded work and retry-safe effects

Separate invocation mechanics from deterministic application behavior.

1/5Cost: Medium to high

SOA and RPC: stable service contracts

Compare service-oriented integration with smaller independently owned services.

1/5Cost: High