Skip to content

Laravel Octane Integration ​

Leakless provides first-class, zero-configuration integration with Laravel Octane (running with the FrankenPHP server driver).

Note: Integration with RoadRunner and Swoole drivers is planned on the project roadmap.


How It Works ​

When themattosdev/leakless is installed in a Laravel application:

  1. Auto-Discovery: Laravel's package discovery automatically loads TheMattos\Leakless\Integrations\Laravel\LeaklessServiceProvider.
  2. Lifecycle Hooks: Leakless automatically registers event listeners on Octane's lifecycle:
    • Laravel\Octane\Events\WorkerStarting / OctaneStarted ➔ Captures the clean initial memory baseline ($M_0$) post-boot.
    • Laravel\Octane\Events\RequestReceived ➔ Takes request snapshot of active PDO connections and Linux kernel memory state.
    • Laravel\Octane\Events\RequestTerminated ➔ Audits uncommitted PDO transactions, triggers automatic rollback if dangling transactions exist, restores output buffers and timezones, and evaluates relative memory drift against the baseline.
  3. Graceful Worker Recycling with Cooldown: If memory drift persists across $N$ consecutive requests post-GC, Leakless safely stops the worker after completing the active response, respecting the recycling cooldown window to prevent restart storms.

Configuration ​

Publish the default configuration file:

bash
php artisan vendor:publish --tag="leakless-config"

This creates config/leakless.php:

php
return [
    'enabled' => env('LEAKLESS_ENABLED', true),

    'max_drift_mb' => env('LEAKLESS_MAX_DRIFT_MB') !== null ? (int) env('LEAKLESS_MAX_DRIFT_MB') : 64,

    'max_rss_mb' => env('LEAKLESS_MAX_RSS_MB') ? (int) env('LEAKLESS_MAX_RSS_MB') : null,

    'consecutive_violations' => (int) env('LEAKLESS_CONSECUTIVE_VIOLATIONS', 5),

    'recycle_cooldown' => (int) env('LEAKLESS_RECYCLE_COOLDOWN', 10),

    'trigger_gc' => env('LEAKLESS_TRIGGER_GC', true),

    'drift_jitter' => (int) env('LEAKLESS_DRIFT_JITTER', 10),

    'max_requests' => env('LEAKLESS_MAX_REQUESTS') ? (int) env('LEAKLESS_MAX_REQUESTS') : null,

    'check_transactions' => env('LEAKLESS_CHECK_TRANSACTIONS', true),

    'check_file_descriptors' => env('LEAKLESS_CHECK_FILE_DESCRIPTORS', false),

    'auto_recycle' => env('LEAKLESS_AUTO_RECYCLE', true),

    'log_violations' => env('LEAKLESS_LOG_VIOLATIONS', true),
 
    'zts_aware' => env('LEAKLESS_ZTS_AWARE') !== null ? filter_var(env('LEAKLESS_ZTS_AWARE'), FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) : null,

    'thread_tolerance_mb' => (float) env('LEAKLESS_THREAD_TOLERANCE_MB', 2.0),

    'unattributed_violations_threshold' => (int) env('LEAKLESS_UNATTRIBUTED_THRESHOLD', 10),

    'resettables' => [
        // App\Services\CartSession::class,
    ],
];

Environment Variables ​

VariableTypeDefaultDescription
LEAKLESS_ENABLEDbooltrueEnable or disable Leakless auditing.
LEAKLESS_MAX_DRIFT_MBint|null64Allowable relative RSS drift (MB) above worker baseline.
LEAKLESS_MAX_RSS_MBint|nullnullHard emergency physical RSS ceiling in MB (optional).
LEAKLESS_CONSECUTIVE_VIOLATIONSint5Consecutive post-GC breaches required before recycling.
LEAKLESS_RECYCLE_COOLDOWNint10Minimum interval in seconds between worker recycles.
LEAKLESS_TRIGGER_GCbooltrueTrigger gc_collect_cycles() on suspected drift breach.
LEAKLESS_DRIFT_JITTERint10Jitter percentage to desynchronize worker restarts.
LEAKLESS_MAX_REQUESTSint|nullnullMaximum request count per worker before recycling.
LEAKLESS_CHECK_TRANSACTIONSbooltrueDetect and automatically roll back open PDO transactions.
LEAKLESS_CHECK_FILE_DESCRIPTORSboolfalseInspect /proc/self/fd for lingering file handles and sockets.
LEAKLESS_AUTO_RECYCLEbooltrueAutomatically signal Octane worker stop on confirmed breach.
LEAKLESS_LOG_VIOLATIONSbooltrueLog diagnostic warnings when leaks or anomalies occur.
LEAKLESS_ZTS_AWAREbool|nullnullEnable ZTS thread-safe memory attribution (null for auto-detect).
LEAKLESS_THREAD_TOLERANCE_MBfloat2.0Minimum Zend MM growth (MB) to attribute drift to the thread.
LEAKLESS_UNATTRIBUTED_THRESHOLDint10Consecutive checks before recycling for native C/unattributed leaks.

State Reset: Octane Flush vs. Leakless Resettables ​

In persistent Laravel Octane applications, handling mutable state in singletons or legacy services is a common challenge. You have multiple options to manage state reset:

1. Laravel Octane Native Mechanisms ​

  • Scoped Bindings: Register services via $this->app->scoped(UserContext::class), flushing instances between requests.
  • Octane Flush List: Add service class names to config/octane.php under the 'flush' key to forget instances on request termination.

2. Leakless Resettables Engine ​

  • resettables in config/leakless.php: Register class strings (to reset static properties/methods), object instances, or callbacks that need cleanups.
  • Declarative #[ResetOnRequest] Attribute: Annotate properties or classes within those registered targets to automatically specify fallback values (default: ...) or custom cleanup methods (resetter: '...').
  • Zero-Reflection in Hot Path: Compiles reset closures at worker startup, ensuring pure native execution during request cycles.

Which One Should You Use? ​

Leakless is designed to be fully modular and flexible. It is at your own discretion which approach to use:

  • You can use Laravel Octane's native scoped() and 'flush' mechanisms to recreate entire service instances.
  • You can use Leakless's resettables (with or without #[ResetOnRequest]) for fine-grained property resets on existing singletons or legacy callbacks.
  • Or you can combine both seamlessly in the same application.

Laravel HTTP Testing Macros ​

When themattosdev/leakless-dev is installed, Leakless injects custom assertion macros into Laravel's TestResponse:

php
test('checkout endpoint leaves clean worker state', function () {
    $response = $this->postJson('/api/checkout', [
        'cart_id' => 1001,
    ]);

    $response->assertOk()
        ->assertNoDanglingTransactions()
        ->assertNoMemoryDrift(maxAllowedMb: 0.25)
        ->assertCleanWorkerState();
});

Released under the MIT License.