I just added $foundRouteMiddleware to Maravel’s Application class to fill a gap that existed. I asked Gemini to present it:
The 404 Firewall: Stop Wasting CPU Cycles on Dead API Routes
If you monitor the raw access logs of any production API, you will notice a frustrating reality: a massive percentage of your incoming traffic is garbage. Automated bots, vulnerability scanners, and rogue crawlers are constantly hammering your servers with requests for routes that simply do not exist.
In a standard PHP framework lifecycle, this creates a hidden performance leak. Most modern monolithic frameworks dump all of their global middleware into a single pipeline that executes before the router even evaluates the URI.
That means when a bot hits GET /wp-admin.php on your headless API, your server might be booting up session handlers, parsing heavy JSON payloads, and executing CORS logic—allocating memory and burning CPU cycles—only to eventually hit a NotFoundHttpException.
In our pursuit of absolute bare-metal performance, the Maravel ecosystem just eliminated this waste entirely. We engineered the Dual-Pipeline Middleware Architecture.
The Architecture: Splitting the Pipeline
To protect the server from doing unnecessary work, we split the traditional middleware stack into two distinct, highly optimized pipelines:
1. The Pre-Routing Pipeline ($middleware)
This is the outer shell. It runs blindly on every incoming request. Because it executes before the framework knows if the route exists, we keep this strictly reserved for the absolute bare minimum (e.g., basic IP blacklisting or catastrophic fail-safes).
2. The Post-Routing Pipeline ($foundRouteMiddleware)
This is the new inner protected shell. By hooking directly into the FastRoute/Trie router’s success state, this array of global middleware only executes if the URI and HTTP method are a perfect match.
If an attacker or bot hits a 404, the router natively throws an impenetrable wall, and this secondary pipeline is completely bypassed. Heavy operations — like database-driven authentication checks, payload mutations, or rate limiters [which should be handled at server level not at app level anyway]— are safely deferred until the route is actually validated.
// app/Application.php
/**
* Global middlewares list that are applied ONLY after the route is found
* Make sure this list has UNIQUE values!!!
*/
protected array $foundRouteMiddleware = [
\App\Http\Middleware\HeavyDatabaseCheck::class,
\App\Http\Middleware\ComplexPayloadParser::class,
];
Micro-Optimizations: The Maravel Way
We didn’t just add a feature; we squeezed every ounce of performance out of the PHP engine while implementing it.
Compile-Time Property Initialization Instead of dynamically assigning these arrays during the application’s runtime boot cycle, we shifted the definitions to strict class properties (protected array $foundRouteMiddleware = [];). This allows PHP to handle the memory allocation once during the compilation phase, shaving off initialization overhead on every single request.
The Ternary Pipeline Merge Merging route-specific middleware with the new global post-routing pipeline presented a potential memory trap. If a route had no specific middleware, executing the framework’s gathering functions would still force PHP to allocate memory for empty arrays.
To bypass this, we implemented a hyper-optimized ternary merge directly in the core:
if ([] !== $this->foundRouteMiddleware || isset($action['middleware'])) {
return $this->sendThroughPipeline(
\array_merge(
$this->foundRouteMiddleware,
isset($action['middleware']) ? $this->gatherMiddlewareClassNames($action['middleware']) : []
),
fn(): mixed => $this->callActionOnArrayBasedRoute($routeInfo)
);
}
If a route doesn’t have custom middleware, PHP immediately drops an empty [] into the array_merge. It saves a complete function call in the execution stack for every single unsecured route request.
The Result: True Share-Nothing Purity
By combining compile-time array initialization, memory-safe ternary merges, and the new 404 Firewall , the framework is now natively immune to bot-induced CPU bloat.
We aren’t trying to force PHP to act like a compiled, stateful daemon. We are letting PHP do what it does best — execute the Doctrine of the Isolated Run — but now, it does it with zero wasted effort.
The engine is lean, the API gates are secured, and the server is strictly reserving its power for the routes that actually matter.
Update
The feature was backported to 10.73.0 kernel and 10.52.55 Maravel template.
This increased the performance for Maravel versus previous versions:
This removes on purpose the possibility for a route middleware to alter the route info in Maravel. Maravelith 20.x will also introduce the limitation. This is what Gemini had to say about it:
Architectural Security Note: Enforcing Route Immutability
Beyond the RPS gains, this refactor addresses a severe architectural vulnerability present in standard pipeline designs: The Pipeline Bypass / Privilege Escalation.
Traditionally, frameworks resolve the route at the end of the pipeline via a stateful container call ($this['request']->route()). This allows developers to mutate the matched route info mid-flight inside a middleware.
While seemingly convenient, this is a dangerous security flaw. If a request matches a public route (bypassing initial authentication gates), a “clever” middleware can hot-swap the destination route info to an administrative action before execution. Because the public pipeline has already finished checking gates, the framework would execute the admin controller without ever running the required auth or admin middleware.
By capturing $routeInfo directly by value using a modern PHP arrow function (fn() =>), Maravel explicitly firewalls the application infrastructure from mid-flight manipulation. The request payload remains mutable, but the route itself is strictly immutable. Whatever the router validates and secures at the gate is exactly what gets executed. No exceptions.


Top comments (0)