Search by

themattosdev / leakless

jmgoncalves97

Zero state and memory leak prevention for PHP persistent runtimes (FrankenPHP & Laravel Octane)

Package info

github.com/themattosdev/leakless

pkg:composer/themattosdev/leakless

Statistics

Installs: 64

Dependents: 1

Suggesters: 0

Stars: 2

Open Issues: 8

v0.9.0 2026-09-10 00:51 UTC

This package is auto-updated.

Last update: 2026-09-10 18:15:17 UTC


README

Leakless Banner

Zero-State & Memory Leak Prevention for Persistent PHP Workers (FrankenPHP, RoadRunner, Swoole, Symfony, Laravel & Vanilla)

Latest Version PHP Version Tests Passing License

Overview

In traditional PHP-FPM, worker processes terminate after each request, allowing the OS to wipe memory and state. Persistent runtimes like FrankenPHP, RoadRunner, Swoole, and Laravel Octane keep PHP in memory across thousands of requests. While significantly faster, long-running workers can suffer from unmonitored C-extension memory growth (outside the Zend VM heap), dangling database transactions, open file handles, and polluted global/static state.

Leakless is an autonomous runtime guardian and static analysis engine for any persistent PHP stack: it reads real Linux kernel RSS from /proc/self/statm, rolls back uncommitted PDO transactions, cleans runtime state with a zero-reflection resettables engine in finally blocks, gracefully recycles workers before OOM Killer strikes, and provides static analysis via PHPStan and Pest assertions.

Installation

# Runtime engine (production)
composer require themattosdev/leakless

# Developer tooling, CLI analyzer, and Pest assertions
composer require --dev themattosdev/leakless-dev

Usage

1. Vanilla PHP / FrankenPHP Loop

use TheMattos\Leakless\DTOs\Config;
use TheMattos\Leakless\Integrations\FrankenPhp\FrankenPhp;

FrankenPHP::run(
    app: function () {
        echo json_encode(['status' => 'ok']);
    },
    config: new Config(
        maxDriftMb: 64,
        maxRequests: 1000,
        resettables: [
            App\Services\CartSession::class,
            fn () => LegacyRegistry::$cache = [],
        ],
    ),
);

2. Laravel Octane (Zero-Config)

LEAKLESS_ENABLED=true
LEAKLESS_MAX_DRIFT_MB=64
LEAKLESS_CHECK_TRANSACTIONS=true
LEAKLESS_CHECK_FILE_DESCRIPTORS=false

In config/leakless.php, you can also register classes or callbacks to auto-reset:

'resettables' => [
    App\Services\CartSession::class,
    fn () => LegacyRegistry::$cache = [],
],

Note regarding Laravel Octane: Octane provides native scoped() bindings and a 'flush' list in config/octane.php. Leakless provides its compiled zero-reflection resettables engine and #[ResetOnRequest] attribute. It is at your own discretion which mechanism to use — you can rely on Octane's native mechanisms, use Leakless's resettables, or combine both seamlessly.

3. Declarative State Reset (#[ResetOnRequest])

Annotate properties or classes to automatically restore initial or default values between requests when registered in resettables:

use TheMattos\Leakless\Attributes\ResetOnRequest;

class UserContext
{
    // Static properties are reset when registering UserContext::class in 'resettables'
    #[ResetOnRequest]
    public static ?string $token = null;

    #[ResetOnRequest(default: 'guest')]
    public static string $role = 'guest';

    // Instance properties are reset when registering the object instance itself
    #[ResetOnRequest(default: [])]
    public array $permissions = [];
}
// In config/leakless.php:
'resettables' => [
    // Resets static #[ResetOnRequest] properties and static cleanup methods:
    UserContext::class,

    // To reset instance properties, register the resolved object instance or callback:
    // fn () => app(UserContext::class)->permissions = [],
],

Important: #[ResetOnRequest] does not automatically scan all classes across your application. To be reset at runtime, the target class (for static state) or object instance (for instance state) must be registered in 'resettables' or via $leakless->registerResetTarget().

4. Automated Testing (Pest & PHPUnit)

test('service executes cleanly without leaking memory or state', function () {
    // 1. Structural design check (no mutable static props or illegal constructor injections)
    expect(PaymentService::class)->toBeLeakless();

    // 2. Full request lifecycle check (PDO transactions, FDs, and Linux RSS drift)
    expect(function () {
        (new PaymentService())->processPendingTransactions();
    })->toRunCleanly(maxDriftMb: 0.25);

    // 3. Deep container/instance property snapshotting (detects runtime state mutations)
    expect(app())->toResetContainerState(function () {
        $this->postJson('/api/checkout', ['item' => 'pro']);
    });
});

5. Static Worker Linter CLI

vendor/bin/leakless analyze

Documentation

Full documentation, architecture guides, kernel memory details, and anti-pattern catalogues are available at:

👉 https://leakless.themattos.dev

Testing & Quality

# Run test suite
docker compose run --rm app vendor/bin/pest

# Code style
docker compose run --rm app vendor/bin/pint --test

# Static analysis (Level 9)
docker compose run --rm app composer analyse

License

Open-source software licensed under the MIT License.
Developed by Jonathan Gonçalves.