Docs Layering

Layering

Layering is not about adding more folders.

Layering is about defining responsibility and controlling dependency direction.

Plumego does not enforce a specific architectural style (such as Clean Architecture or DDD),
but it strongly encourages a layered structure with explicit boundaries.

This document explains the layering model Plumego is designed to support.


Why Layering Matters in Plumego

Plumego deliberately keeps the framework thin and constrained.

As a result:

  • Plumego will not protect you from architectural drift
  • Poor structure will surface quickly
  • Good structure will pay off for years

Layering is the primary tool for managing complexity in long-lived Plumego systems.


The Core Principle: Dependency Direction

The most important rule is simple:

Dependencies must point inward, never outward.

This means:

  • Inner layers must not depend on outer layers
  • Framework code must not leak into domain logic
  • Transport details must remain at the edges

Everything else follows from this rule.


A typical Plumego application can be structured into the following layers:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         HTTP Layer          β”‚  ← Plumego
β”‚  (Router, Middleware,       β”‚
β”‚   Handlers)                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Application Layer       β”‚
β”‚  (Use cases, services)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚        Domain Layer         β”‚
β”‚  (Entities, core rules)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Infrastructure Layer     β”‚
β”‚  (DB, cache, external)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Not every project needs all layers on day one.
But the direction of dependencies must remain consistent.


HTTP Layer: The Boundary Layer

The HTTP layer includes:

  • Router
  • Middleware
  • Handlers
  • Request/response formatting

Responsibilities:

  • Translate HTTP requests into application calls
  • Translate application results into HTTP responses
  • Handle protocol-level concerns only

Rules:

  • May depend on Application layer
  • Must not contain business logic
  • Must not be depended on by inner layers

This layer is where Plumego lives.


Application Layer: Use Cases and Coordination

The application layer coordinates behavior.

It contains:

  • Use cases
  • Application services
  • Workflow orchestration

Responsibilities:

  • Express what the system can do
  • Coordinate domain objects
  • Enforce application-level rules

Rules:

  • May depend on Domain layer
  • Must not depend on HTTP or Plumego
  • Should be testable without HTTP

This layer represents system behavior, not protocol.


Domain Layer: Core Business Rules

The domain layer is the heart of the system.

It contains:

  • Entities
  • Value objects
  • Domain rules
  • Domain errors

Responsibilities:

  • Represent core business concepts
  • Enforce invariants
  • Remain stable over time

Rules:

  • Must not depend on Plumego
  • Must not depend on HTTP
  • Must not depend on infrastructure details

If a rule changes often, it probably does not belong here.


Infrastructure Layer: Implementation Details

The infrastructure layer contains:

  • Database implementations
  • Cache clients
  • External service adapters
  • Message brokers

Responsibilities:

  • Implement interfaces defined by inner layers
  • Handle IO and side effects

Rules:

  • Depends inward (Application / Domain)
  • Should be replaceable
  • Must not define business rules

Infrastructure is where volatility is expected.


A Concrete Directory Example

A simple Plumego project might evolve into:

internal/
β”œβ”€β”€ http/
β”‚   β”œβ”€β”€ handler/
β”‚   └── middleware/
β”œβ”€β”€ app/
β”‚   └── usecase/
β”œβ”€β”€ domain/
β”‚   β”œβ”€β”€ user/
β”‚   └── order/
└── infra/
β”œβ”€β”€ mysql/
└── redis/

This is only one possible layout.

The important part is not the names β€”
it is who depends on whom.


What Plumego Does Not Enforce

Plumego does not enforce:

  • A specific folder structure
  • A specific naming convention
  • A specific architectural pattern

It provides a framework edge that fits naturally into layered designs.

Discipline must come from the team.


Common Layering Mistakes

Letting HTTP Types Leak Inward

Avoid passing *plumego.Context into application or domain code.

This couples core logic to transport details.


Putting Business Logic in Handlers

Handlers should translate, not decide.

Business rules belong inward.


Making Infrastructure the Center

Database schemas and external APIs should not define your system’s structure.

They are implementation details, not the model.


Layering and Long-Term Evolution

Good layering enables:

  • Changing frameworks without rewriting core logic
  • Supporting multiple transports (HTTP, RPC, CLI)
  • Incremental refactoring instead of rewrites

This is the primary reason Plumego emphasizes boundaries.


Summary

Plumego encourages a layered architecture where:

  • Responsibilities are clear
  • Dependencies flow inward
  • Framework code stays at the edges
  • Core logic remains independent and stable

Layering is not optional for long-lived systems β€”
it is the foundation of maintainability.


Next

With layering established, the next architectural concern is:

β†’ Boundary Definition

This explains how to draw and protect boundaries between layers in practice.