Most explanations of APM stop at the dashboard. But the part that decides whether monitoring costs you latency, survives a vendor outage, or quietly leaks memory on Octane is the agent — the component that actually sits in or beside your app collecting the data. It's the least glamorous piece and the one whose design you'll feel the most.
Three agent architectures
1. In-process (library)
A composer package that registers inside your Laravel app. Captures telemetry synchronously during the request and ships it via HTTP after the response. Examples: Laravel Telescope, Sentry's default PHP SDK, Flare's SDK, Inspector.dev's Laravel package.
Pros: easy install (composer require + done), no extra process to supervise, works on any host.
Cons: overhead hits every request (typically 5-50ms), HTTP shipping can block on vendor outages if not queued, accumulates memory on persistent workers like Octane.
2. Out-of-process (daemon)
A separate long-running process — usually a ReactPHP daemon or system service — that buffers telemetry from your Laravel app and ships it to the dashboard asynchronously. Examples: NightOwl's agent, Laravel Nightwatch package's agent, Datadog's Lambda Extension.
Pros: sub-1ms request-path overhead, crash isolation (agent crash doesn't take down your app), graceful handling of vendor outages (buffers telemetry locally).
Cons: need to supervise the extra process (Supervisor, systemd, Forge daemons), slightly more setup, doesn't fit serverless like Lambda without a Lambda Extension variant.
3. System extension (PHP extension)
A compiled PHP extension that hooks into the runtime at a low level. Can capture data userland PHP can't see — opcache stats, runtime-internal timings, zero-overhead stack sampling. Examples: New Relic PHP agent, Tideways PHP extension.
Pros: maximum data richness, often lowest per-request overhead, captures things composer packages can't.
Cons: requires root access to install, has to match your PHP version exactly (breaks on upgrades), ties you to the vendor.
How NightOwl's agent works
Laravel request flow
├── Request arrives at PHP-FPM / Octane worker
├── Nightwatch package observes events (queries, jobs, exceptions, etc.)
├── Events serialized to a local TCP socket (port 2407)
├── Worker returns response to user ← latency budget ends here
│
└── NightOwl agent (separate ReactPHP process)
├── Receives events asynchronously from all app workers
├── Buffers in-memory queue
├── Batch-writes to your PostgreSQL via COPY protocol
└── Retries on transient failuresRequest-path overhead: serialize + socket write = under 1ms. All heavy lifting (validation, batching, PostgreSQL COPY) happens in the separate agent process. Benchmarked at 13,400 payloads/s single-instance.
Why architecture matters for Octane
In Octane, a worker handles thousands of requests without dying. In-process agents accumulate state — event buffers, retry queues, observer registrations — across every request the worker handles. Memory grows; eventually the worker OOMs or slows.
Out-of-process agents immunize you: the agent's state is in its own process; the Laravel worker holds nothing across requests beyond a socket connection. This is why NightOwl's architecture is Octane-native and why some SDK-based APMs require extra work to be Octane-safe.