awesome-everything RU
↑ Back to the climb

Backend Architecture

Middleware and DI: wire a testable service

Crux Hands-on project — build a small service with a correct middleware pipeline and an injected, composition-rooted object graph, then prove the seam, scopes, and ordering with tests and a load run.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 240 min

Reading about the two axes is not the same as wiring them. Build a small service where the middleware pipeline is deliberately ordered, the object graph is assembled in one composition root, every scope choice is justified, and the testing seam is real — then prove each property with a test or a measurement.

Goal

Turn the unit’s mental model into a working service: a correct, ordered middleware pipeline; a composition root with no hidden new in business logic; deliberate singleton/request/transient choices; a seam you exercise with both a fake and a boundary mock; and evidence that the ordering and scopes behave as intended under load.

Project
0 of 7
Objective

Build a small HTTP service (Express, Koa, Fastify, or NestJS) with one real domain use-case (e.g. place an order or create a user) whose middleware pipeline and dependency graph are both correct by design — then prove correctness with tests and a short load run, not assertion.

Requirements
Acceptance criteria
  • A request flows end-to-end through the ordered pipeline; an unauthenticated or rate-limited request is rejected before the expensive body-parsing step, demonstrated by a test or a log/trace.
  • No business-logic class constructs its own collaborators — the entire graph is assembled in the composition root, verifiable by grepping the domain code for new on injected types.
  • The state-based test survives a behavior-preserving refactor (e.g. splitting one save into two) while the boundary mock still verifies the external call — showing you mocked the boundary and faked what you own.
  • Every provider's scope is justified, and a short note explains why no singleton holds per-request state and why any request-scoped provider was unavoidable.
Senior stretch
  • Introduce a deliberate circular dependency between two services, observe the container's resolution error, then remove the cycle by extracting a shared third class — and write up why forwardRef would only have hidden it.
  • Add a request-scoped provider deep in the graph, load-test before and after, and measure the allocation/latency cost of scope bubbling versus passing the value as an argument.
  • Switch the eager/lazy startup mode (or simulate a missing dependency) and show that eager instantiation turns a misconfiguration into a loud boot-time crash instead of a quiet first-request failure.
  • Port the same service to a second framework (e.g. Express to Fastify) and compare how the middleware model and encapsulation differ for the same pipeline.
Recap

This is the loop you run on every real backend: order the pipeline so cheap rejections come first and one terminal error handler catches the rest; assemble the graph in one composition root so no logic class constructs its own collaborators; choose each scope deliberately and keep singletons stateless; and use the seam to fake what you own and mock the boundaries you don’t. Doing it once on a small service makes the two axes — request and wiring — automatic when you read a production codebase.

Continue the climb ↑Blocking vs non-blocking I/O: two ways to wait
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.