Maybe not microservice: The Case for Pipes, Pipelines, and Functional Isolation
1. Subsystem Decomposition 1.1 The Decomposition Problem A subsystem decomposes a codebase into smaller, cohesive units. Two primary axes of decomposition exist: Technical axis : grouping by component type (controller, service, model, view) Functional axis : grouping by business capability (cataloguing, circulation, etc.) 1.2 Tension Between Framework Prescriptions and Decomposition Strategy Organizing top-level subsystems functionally may create friction with frameworks that prescribe a technical-first structure. Concrete examples: Rails enforces model, view, and controller directories at the root level, making functional decomposition awkward without additional mechanisms like Rails Engines Sinatra (a microframework) imposes minimal structure, leaving architectural decisions entirely to the team Frameworks with rigid prescriptions constrain architectural choices. Frameworks with no structure shift the entire burden onto the team with no guidance. This second approach might be fine for teams that know what they are doing and how to shape the architecture properly. Not everyone needs guidance from the framework. 1.3 Contexts as a Middle Ground Phoenix provides contexts as a compromise: Explicit, guideline-oriented subsystems that enable functional decomposition without rigid enforcement Contexts define functional boundaries while allowing technical organization to remain nested within them Functional blocks may later evolve into microservices, but this is optional The same decomposition serves equally well in a modular monolith or a distributed architecture The choice depends on team needs, scaling requirements, and operational maturity, not on the decomposition strategy itself 2. Pipeline Topology and Data Flow 2.1 The Unix Pipeline Model Unix pipelines model data flow through a single stream connecting stdout to stdin. This forms a linear chain where each stage's output becomes the next stage's input. Key characteristics: Each stage has exactly one input and one o