Skip to content
Personal Experience Blogs
Go back

What Breaks When Your Server Doesn't Restart. | The Foundation Papers, Part 6

PHP-FPM forgives you in a way Octane doesn’t. Every request got a clean process, a clean memory space, every static property reset by the time the next user hit the same endpoint. You could put user data on a class property, ship it, and never notice — because the process died before it could leak into somebody else’s request.

Octane keeps the process alive. That’s the entire performance win — no bootstrapping Laravel from scratch on every request — and it’s also where every leftover assumption from the PHP-FPM era turns into a live bug. A singleton service with a property set from $request->user() on the first request will still have that user’s data on the fiftieth request, served to somebody else entirely, unless the service was written knowing it would outlive the request that created it.

This isn’t a rare mistake. It’s the default outcome of writing Laravel the way Laravel has been taught for a decade, then dropping it onto Octane without re-examining a single binding.

core-foundation treats this as an architectural rule, not a warning in a README someone skims once. Repositories are always bound transient — bind(), never singleton() — because a repository sitting on the container across requests is exactly the shape of bug described above, just one layer removed. Services default to scoped(), which resets per request under Octane and behaves like a normal singleton everywhere else, so the same service class is safe in both worlds without a developer needing to know which world they’re deploying to. Genuinely stateless services — the ones with no request data, no user data, nothing but pure logic — are the only ones allowed singleton(), and that’s a deliberate exception, not the default anyone reaches for out of habit.

// ServiceProvider — the rule this entire post is about
$this->app->bind(OrderRepositoryInterface::class, OrderRepository::class); // transient, always

// Domain state that must never leak across requests or modules
class OrderContext extends ApplicationContext
{
    protected function prefix(): string
    {
        return 'order'; // mandatory per-domain namespace — no key collisions, ever
    }
}

The subtler failure mode is tenant data. In a single-database multi-tenant Laravel app, a cache key or a static property that doesn’t account for which tenant is currently being served is a cross-tenant data leak waiting for the exact wrong moment to happen — under Octane, that moment arrives faster, because the process serving tenant A’s request might serve tenant B’s request eleven milliseconds later. core-foundation’s cache scoping ties every cache tag to the current tenant automatically, so a cache hit for one tenant is structurally incapable of returning another tenant’s data, regardless of what request happened to warm that cache.

None of this is exotic. It’s the same discipline distributed systems engineers have always needed — don’t assume shared state is safe just because it’s convenient — applied to a runtime model most Laravel developers didn’t grow up with. Octane didn’t introduce new bugs. It removed the thing that used to hide them.

If you’re running Octane, or planning to, this is the layer worth auditing before your first production incident teaches you the hard way: which of your bindings assume a process dies after every request, and what happens the day it doesn’t.

This safety discipline ships in the free, MIT core — it’s too important to gate behind a price. What’s paid is the tooling that shows you the effect in real time: Server-Timing profiling that puts your Octane request lifecycle directly in Chrome DevTools, so “is this actually fast under load” stops being a guess. That’s part of the Pro tier at https://packagist.org/packages/rupeshstha/core-foundation.

composer require rupeshstha/core-foundation — Application Context and the full binding-strategy rationale: Application Context · Repositories


Share this post on:

Previous Post
The Incident That Made Me Charge For This. | The Foundation Papers, Part 7
Next Post
Cache That Knows When to Forget. | The Foundation Papers, Part 5