Skip to content

ResourceMetadataProvider keeps every serialised resource for the life of a worker (memory leak in FrankenPHP worker mode) #448

Closed

Description

@silverbackdan

From components-web-app/components-web-app#161 (alongside api-platform/core#8680).

Silverback\ApiComponentsBundle\Serializer\ResourceMetadata\ResourceMetadataProvider::$metadatas stores every serialised resource object and its ResourceMetadata, keyed by spl_object_id. Nothing ever clears it: it has no ResetInterface and no kernel.reset tag. In worker mode it keeps every request's resources (and the entity graphs they reference) alive until the worker restarts.

Measured in the template. API Platform 5.0.3, bundle 2.0.0-alpha.20, prod env. One booted kernel, and handle → terminate → services_resetter->reset() per request, as a worker does. The template already tags API Platform's skolem converter for reset (#161), so its genid map stays empty.

300 requests to Services resetter only Also clearing $metadatas
A form component 44.5 → 127.4 MB 41.4 MB, flat
A navigation link 42.3 → 57.3 MB 38.9 MB, flat

The runtime's FRANKENPHP_LOOP_MAX (500) hides most of it, but a form-heavy, uncached workload reaches the template's 128M memory_limit before the restart.

Also a correctness risk: after an object is freed, spl_object_id can be reused by a different object. The map only avoids that today because it never frees anything. If it's cleared mid-request, or the entries become weak, a new object could pick up another object's metadata. A WeakMap keyed by the object would fix both problems.

Suggested fix: implement ResetInterface (reset(): $this->metadatas = []) and tag the service kernel.reset, or use a WeakMap<object, ResourceMetadata>. Add a test that the services resetter clears it.

Related: API Platform's own half, SkolemIriConverter not tagged kernel.reset, is api-platform/core#8680, with the fix in #8681. Until an API Platform release has it, the template carries a compiler-pass hotfix (#161). The bundle could carry the same hotfix for every bundle user, which would let the template drop its own.

Activity

  1. silverbackdan commented on Oct 13, 2026

    @silverbackdan
    CollaboratorAuthor

    Fixed in #449 (merged as 1625424). ResourceMetadataProvider keeps metadata in a WeakMap and is reset between requests, so spl_object_id keys are gone. ApiPlatformCompilerPass tags API Platform's skolem IRI converter kernel.reset until api-platform/core#8681 is released, so the template can drop its own hotfix (#161). Also reset now: PropagateUpdatesListener (a failed flush no longer leaks into the next request's purges and Mercure updates) and the user email factories. ResetInterfaceServicesTest fails for any bundle service implementing ResetInterface without kernel.reset, and worker_mode_memory.feature asserts both maps are empty after each services reset through one kernel.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions