paulserban.eu

Writing Edition

Paul Serban

Writing, snippets & book notes

Cheat sheet - Post

Architectural Modularity vs. Service Granularity

← Back to Architectural Modularity vs. Service Granularity: Unpacking the Differences for Modern Software Design

Architectural modularity (how code is internally organized) and service granularity (how functionality is split across network-exposed services) are two distinct design levers that are frequently conflated, and mixing them up leads to costly architectural mistakes.

Overview

Key Concepts

Architectural Modularity

export interface PaymentGateway {
  charge(amount: number, currency: string): Promise<boolean>;
  refund(transactionId: string, amount: number): Promise<boolean>;
}
// Swappable implementation behind the contract:
export class StripeGateway implements PaymentGateway { /* ... */ }

Service Granularity

Migration Path: Modularize, Then Extract

Supporting Patterns

Trade-offs / Caveats

Example in Practice

An e-commerce platform illustrates the full spectrum: internally, payment, inventory, and auth are cleanly separated TypeScript modules with dependency-injected contracts (OrderManager depends on a PaymentProcessor interface, not a concrete class). Externally, during Black Friday, only the inventory and order-processing services need to scale - if the team over-fragments into "nano-services" (separate services for tax calc, currency conversion, discount codes, etc.), a single order now requires many chained network calls and any one outage cascades into checkout failures. The balanced approach: keep tightly related, always-co-invoked logic (e.g., pricing) consolidated into one service aligned to a bounded context, and use event-driven messaging (publish_event('OrderPlaced', ...)) to coordinate the independently-owned inventory and shipping databases without reintroducing tight coupling.

Related topics