Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Performance Testing Laravel Package

volt-test/laravel-performance-testing

A Laravel package for performance testing and benchmarking. Define scenarios, measure response times and database queries, and set assertions to catch slowdowns and regressions before they reach production.

View on GitHub
Deep Wiki
Context7

Getting Started

Install as a dev dependency and keep it out of production:

composer require --dev volt-test/laravel-performance-testing

Look first at, in this order:

  1. The README — the package is small and the README is the canonical API surface. Read the "assertions" / "usage" section before anything else.
  2. composer.json — confirm the supported Laravel and PHP matrix (v1.3.3 adds PHP 8.5 to the test matrix, so 8.4/8.5 are safe; check the constraint floors against your app).
  3. src/ — one or two traits plus a handful of support classes; skim ServerHealth/health-check classes since that is what v1.3.3 touched, and any Performance/Assert trait to see exactly what is exposed.
  4. config/ — if the package ships a config file, publish it (php artisan vendor:publish --tag=...) and read every key before tuning thresholds.

Your first use case should be the smallest possible: one test that hits your hottest public route and asserts a duration budget and a query-count budget.

it('serves the homepage within budget', function () {
    $this->get('/')
        ->assertPerformance();       // adjust to the actual helper names in the README
});

Run it once locally with Xdebug off to get a realistic baseline, then commit it. Do not start by wrapping your entire route table — you will spend the first week fighting flaky assertions instead of finding real regressions.

Implementation Patterns

Separate the performance suite from the unit suite. Put performance tests in tests/Performance and wire a dedicated Pest/PHPUnit testsuite (or a @group performance annotation) so composer test stays fast and deterministic while composer test:perf runs the slow, environment-sensitive checks. Most teams run the perf suite on a schedule or on PRs targeting main, not on every push.

Adopt a budget, not a benchmark. Assert against an explicit ceiling that is generous enough to survive noisy CI hardware (e.g. "under 400ms", "under 25 queries") rather than a tight number copied from your laptop. The value of this package is catching a 10x regression, not a 5% one.

Use query counts and memory as the primary signals, wall-clock time as the secondary one. Query count and peak memory are far more stable across runners than elapsed milliseconds. A pattern that ages well:

it('does not N+1 the order index', function () {
    Order::factory()->count(30)->create();

    $this->actingAs($user)
        ->get('/orders')
        ->assertQueryCountLessThan(20);   // illustrative
});

Drive many routes from a dataset. In Pest, a dataset of [uri, maxDuration, maxQueries] triples lets you cover a dozen endpoints in one test body and tune each independently. This scales far better than copy-pasting a test per route.

Warm up before measuring. The first request in a test process pays for container boot, config resolution, and view compilation. If the package's assertion measures the request you just made, either issue a throwaway request first or run the assertion against a cached-config, cached-route environment so the number reflects steady state.

Gate thresholds by environment. Read the budgets from config or from env() in the test itself, so CI runners (slow, shared) get looser numbers than a developer machine. Hardcoding one number guarantees someone disables the suite.

Put the server health check into your deploy pipeline. The class touched in v1.3.3 exists to validate the runtime environment. Run it as a post-deploy or pre-traffic step (artisan command or a small script) so OPcache settings, PHP version drift, and similar host-level misconfigurations surface before users find them.

Pair it with Laravel's own tooling. Use DB::listen / Model::preventLazyLoading() in the performance suite to turn lazy-loading into a hard failure, and let this package own the budget assertions. The two complement each other rather than overlapping.

Gotchas and Tips

  • v1.3.3 is a patch release with no breaking changes. The only behavioural change is silencing a PHP 8.4+ deprecation inside the server health check. If you are on PHP 8.4 or 8.5 and were seeing deprecation noise from this package, upgrade — it is a safe composer update with no code changes required.
  • Timing assertions are inherently flaky. Never assert sub-100ms budgets on shared CI. If you must, allow a retry or take a median of N runs. A red build that is really a noisy neighbour will get the suite deleted within a month.
  • Xdebug, Telescope, and query logging will destroy your numbers. Disable all three in the performance test environment. A forgotten TELESCOPE_ENABLED=true in .env.testing is the single most common cause of "why is this suddenly 3 seconds".
  • Config and route caching change the measurement. Decide deliberately whether you measure the cached or uncached path, and be consistent. Measuring the uncached path in CI tells you nothing about production.
  • APP_DEBUG=true inflates memory and time. Confirm the testing env has it off; the difference is routinely 2–3x.
  • Debugging a failing assertion: run the single test with --filter, then dump the actual measurement rather than only the assertion message. Most failures are a single bad route (a missing with() on an eager load) rather than a systemic slowdown.
  • Watch the database driver. SQLite in-memory is dramatically faster than MySQL/Postgres for query-heavy routes, so query-count budgets travel well between drivers but duration budgets do not. Prefer query counts for anything you want to be portable.
  • Factory data volume is part of the test. An N+1 that is invisible with 3 rows becomes a 900-query disaster with 500. Seed enough rows that the query-count assertion is meaningful.
  • Health check output is environment-specific. Don't assert on exact strings from the health check in your own tests; assert on the exit code or a structured result, otherwise a patch release (like this one) that adjusts the check can break your suite.
  • Extension points: the assertions are thin wrappers, so when you need something the package doesn't expose (e.g. a p95 over multiple runs), write your own helper in tests/Performance/Concerns rather than forking. Keep custom thresholds in one config file so the whole team tunes them in one place.
  • Upgrade cadence: this package moves in small patch releases. Pin with a caret constraint (^1.3) and let Renovate/Dependabot open PRs — patches have historically been deprecation and compatibility fixes, which is exactly what you want flowing automatically on the PHP 8.4→8.5 upgrade path.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin