Skip to content

GreaseGet greased.

Opt-in performance across Laravel's hot paths β€” a menu of independent, byte-identical tiers spanning the whole request lifecycle, from Eloquent to the router, the view finder, and the query grammar. Take the ones whose hot paths you run.

Grease

Start with one trait ​

php
use Grease\Concerns\HasGrease;

class User extends Model
{
    use HasGrease; 
}

An endpoint that lists 100 users and serializes them to JSON drops from 3.58 ms to 0.46 ms β€” real SQL included, not a micro-benchmark. That's :memory: SQLite, where Eloquent is most of the request; against a networked database the same ~3.1 ms come off a larger total, so the percentage is smaller while the time removed holds (how to read these honestly).

That's the model and event tiers together. The model trait alone is the easiest win and a fine place to stop β€” but Grease is a menu, and the rest of it lives across the request, not just in Eloquent:

  • Model β€” use HasGrease; (or extend Grease\GreasedModel): hydration, casting, serialization, dirty-checking. Per-row Γ— per-attribute. Zero config.
  • Providers you register β€” a faster event dispatcher, Blade compiler, config repository, validator, and query grammar: each one line in bootstrap/providers.php.
  • App-entry swaps β€” a greased container, request, and router: a one-line edit where each is constructed, before any provider runs.
  • Deploy caches β€” grease:config-cache, grease:route-cache, grease:view-cache: drop-in twins of Laravel's own *:cache that take once-per-request resolution to ~free.

The same idea runs under all of them. Laravel re-derives the same stable facts over and over — the casts array and a fresh ReflectionClass per hydrated row, the merged input map on every $request->input(), a config key's dot-walk on every config(), a route's middleware resolve-and-sort and a view's name→path stat-walk on every request, an identifier's quoting on every query. None of it changes for the life of the process. Grease computes each fact once and reuses it — byte-for-byte the same result, a fraction of the work.

Each of these was proposed to Laravel core and declined on reasonable grounds β€” every one "marginal in isolation." Individually, maybe. Layered on a real request β€” booted, routed, hydrated, rendered, serialized β€” they move the number you actually pay for. Grease is where that declined work lives β€” see the history.

Byte-identical to vanilla, or it's a failing test.

Get greased β†’

Byte-identical to vanilla, or it's a failing test. Β· MIT Licensed