onelearningcommunity/grease
Grease is a menu of independent, byte-identical performance tiers for Laravel's hot paths—Eloquent hydration, casting and serialization, events, Blade, config, validation, the container and router. Opt in per tier; the model trait is the zero-config starting point. Zero framework changes, and anythi...
Illuminate\Database\Eloquent\Model, routing, request input handling, and Blade component attribute bags. Architecture fit remains high for teams that accept a fast-moving dependency tracking upstream patch releases; it is low for teams that treat framework internals as frozen ground.withCasts() being ignored on greased rows, and runtime setTable() on partitioned/archive models producing rows whose save()/delete() targeted the class table. Both were silent data-correctness issues, not performance quirks. The new HasGreaseWholeStateParityTest (cold/warm/hydrated full instance-state comparison, with a tripwire that fails when Laravel adds a new Eloquent attribute class) is the single most important thing in this release for a TPM: it converts "trust us, output is identical" into an executable, CI-enforced claim.^12.69.2 || ^13.33 replaces the prior "Laravel 10.x+" framing. Laravel 10/11 shops are now out of scope entirely, and even Laravel 12 shops must be on a recent patch line, not just the major.^12.69.2 || ^13.33 — Composer will simply not offer 0.9.1 below those floors. Teams must composer update within their major first.GreaseRoutingServiceProvider had a URL fast-path defect where %, ?, # were emitted raw, truncating generated paths. Fixed in 12.69.2/13.31-mirroring code. If you run that provider on 12.69.2+, 0.9.1 is a required upgrade, not an optional one — this is the only item in the notes with an explicit "upgrade" instruction.withCasts(), partitioned/setTable() models, and #[Refreshes] if you use them.withCasts() should treat 0.9.0 as unsafe and audit that window.HasGreaseWholeStateParityTest — full instance-state parity across cold/warm/hydrated paths.getTable() overrides (sharded, AsPivot, custom) are called per row as in vanilla — check that against your model counts.GreaseRoutingServiceProvider? If yes on 12.69.2+, this upgrade is mandatory — what is the rollout window?withCasts(), runtime setTable() (partitioned/archive tables), #[Refreshes], or trait-based class attributes? These are the exact surfaces 0.9.1 touched; each needs a targeted regression test.Request::all() key ordering or ComponentAttributeBag::merge() style output? Both changed behaviour to match vanilla — snapshot tests on forms/uploads and Blade style defaults should be checked.^0.9? Who reads the changelog on each bump?Model internals (stancl/tenancy with runtime setTable(), spatie/laravel-activitylog, laravel-nestedset) — the setTable() fix directly implicates tenancy/sharding setups.withCasts() usage and any model whose table is set at runtime. Verify hydrated rows write to the correct table. Treat this as a data-integrity audit, not a code review.composer update within your Laravel major to reach 12.69.2+/13.33; confirm PHP 8.2+ (8.2–8.5 supported). Laravel 10/11 requires a framework upgrade project — sequence that separately and do not bundle it with Grease adoption.0.9.1 (pre-1.0 semver). Install with optimizations disabled (Grease::disableAll()) in staging; run the existing suite to prove no regression from the dependency alone.withCasts(), runtime setTable(), #[Refreshes], Request::all() ordering/upload collisions — plus Blade style merge output if you use it.^12.69.2 || ^13.33. Patch-level floors are enforced by Composer — this is a hard gate, not guidance.setTable() fix should be validated on your primary driver and any archive driver.Model state or table resolution at runtime (stancl/tenancy, sharding packages, AsPivot implementers) — the 0.9.1 fix makes these work like vanilla, but they are the highest-variance integration surface.Grease::debug() for applied optimizations, Grease::disableFor(Model::class) for per-model isolation. New in this release: the whole-state parity test is a usable template for reproducing a divergence in your own app.getTable() overrides on large result sets.getTable() calls on high-cardinality result sets are a scaling cost worth measuring.| Failure Scenario | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Laravel patch changes an overridden method; Grease silently diverges | Medium (demonstrated between 0.9.0 and 0.9.1) | Wrong data — ignored casts, writes to wrong table | Stay on supported patch floors; watch the package's weekly CI; run targeted parity tests in your own suite |
Version floor blocks upgrade (^12.69.2 || ^13.33) |
High for L10/L11 estates | Adoption impossible without a framework upgrade | Sequence Laravel upgrade as its own project; do not bundle |
Routing URL truncation on %/?/# |
Low post-fix; certain if staying on 0.9.0 with GreaseRoutingServiceProvider on 12.69.2+ |
Broken/truncated generated URLs | Mandatory upgrade to 0.9.1 |
Hydration divergence with custom Eloquent logic (withCasts, setTable, #[Refreshes]) |
Low post-fix | Corrupt or mis-targeted writes | Disable per model via Grease::disableFor(); add parity tests for these surfaces |
| Memory growth from lazy hydration | Low–Medium | OOM under load | Monitor peak memory; disable optimization if breached |
Request::all() key ordering / upload collision behaviour change |
Low | Form or upload handling edge cases | Snapshot-test upload endpoints |
| Package abandonment or stalled 1.0 | Low | No fixes for future Laravel changes | MIT license permits fork; the parity harness makes a fork tractable |
| Performance regression in untested query shapes | Medium | Slower queries in specific patterns | Feature-flag per model/endpoint; A/B test |
Grease::enable(), disableFor()), how to read Grease::debug(), and the one rule that matters — check the Laravel patch level before debugging anything else.laravel-nestedset); the changelog-review ritual.withCasts(), runtime setTable(), Request::all() ordering, and Blade style merging; a documented checklist for each Grease version bump.Grease::disableAll()) — no schema or data migration to reverse; per-model disable for narrow blast radius; keep the previous pinned version in composer.json history for a one-line revert; for routing-provider issues, disable that provider independently.How can I help you explore Laravel packages today?