// Case study · Platform / infrastructure
Fleet runtime & observability
Moved a dozen payment services onto a long-running PHP runtime, with standardized structured logging and metrics — so the fleet is faster, observable and production-ready on Kubernetes.
The problem
A payment platform is a fleet of PHP services. On classic FPM / FCGI they pay a per-request bootstrap tax, and without shared logging, metrics and health conventions each service is a different black box in production — hard to debug when money is moving and something stalls.
The approach
I drove the cross-cutting work: migrating services from FPM / FCGI to a long-running RoadRunner runtime (with middleware to keep Doctrine and request state clean between requests), standardizing structured JSON logging with per-service channels and enriched records, a shared metrics SDK, and readiness / liveness probes plus hardened container images so everything runs cleanly on Kubernetes.
The decision & trade-off
A long-running runtime is faster but unforgiving — state leaked between requests becomes a real, subtle bug. We accepted that cost and paid it down with runtime middleware (ORM filter / state cleanup) and shared conventions, in exchange for lower latency and a fleet that behaves consistently.
Architecture
Shared building blocks — a logger bundle, a metrics SDK, RoadRunner runtime config and probes, and common base images — that every service adopts, so runtime behavior and observability are the same across the fleet instead of reinvented per service.
Outcome
A dozen services on one runtime and one observability story: structured logs and metrics everywhere, health-checked and K8s-ready, with the per-request bootstrap tax gone.
What I'd do differently
Wrap the RoadRunner state-hygiene rules in stronger guardrails earlier — the subtle between-request state leaks were the hardest bugs to chase.
Architecture diagram
Stack
- PHP
- RoadRunner
- Kubernetes
- Monolog
- Docker
Have a similar problem?
Tell me about it — I reply within a day.