Skip to content

⚡ Cache the schema on every environment that runs without debug - #290

Open
Mir-Zairan wants to merge 2 commits into
thecodingmachine:masterfrom
Mir-Zairan:fix/cache-schema-outside-debug
Open

Mir-Zairan wants to merge 2 commits into
thecodingmachine:masterfrom
Mir-Zairan:fix/cache-schema-outside-debug

Conversation

@Mir-Zairan

@Mir-Zairan Mir-Zairan commented Sep 16, 2026

Copy link
Copy Markdown

The compiler pass only puts the schema factory in prod mode when the environment is literally named prod. Call it staging, preprod, uat or qa and it falls through to the factory default, dev mode, which checks every controller and type file for changes on every request.

Nothing reports this, so it is easy to run for years without noticing. We found it chasing a slow page on staging: 1.8s per GraphQL call, 0.12s once the schema was cached, with the database work taking milliseconds either way.

Checking files for changes is what kernel.debug means in Symfony, so that drives it now instead of the environment name.

The second commit adds schema.auto_reload for the environments that do not fit that rule, defaulting to '%kernel.debug%' the way Twig's own auto_reload does. A staging server running with debug on can keep the cache, and a debug-off setup can keep picking up edits.

Two behaviour changes for the release notes. An environment with debug off and a name other than prod now caches the schema, and prod with debug on now reloads it.

The README has a "Schema caching" section: the default, what each setting changes, an override example, and that a debug-off deploy has to clear the cache when a controller or type changes.

Tests cover staging with debug off, prod with debug on, and both explicit overrides, checking that the other mode is not configured. The test kernel hardcoded debug on and the test environment, so it takes both now, and gets its own cache directory when debug is off, otherwise it would reuse a dumped container and hide changes to the pass.

The compiler pass only put the schema factory in prod mode for the environment
literally named "prod". Any other name - staging, preprod, uat, qa - fell through
to the factory default, dev mode, which stats every controller and type file and
re-globs the configured namespaces on each request.

That is what kernel.debug already means in Symfony, and it is what Twig's
auto_reload and Doctrine's proxy autogeneration key on, so use it here too.
@Mir-Zairan
Mir-Zairan force-pushed the fix/cache-schema-outside-debug branch from d78872d to be2e6db Compare September 16, 2026 12:48
@Mir-Zairan

Copy link
Copy Markdown
Author

@enricobono @Lappihuan @andrew-demb Kindly review the pr.

@andrew-demb andrew-demb left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the proposal. Let me share my throughts on the topic.

I think using kernel.debug as the default is the right direction, but it would be useful to keep schema reloading independently configurable.

Could we expose an option like this?

graphqlite:
    schema:
        auto_reload: '%kernel.debug%'

This would preserve the proposed behavior by default while allowing applications to override it - for example, staging with debug enabled but schema caching retained, or a debug-off development environment that should still detect schema changes.

auto_reload should mean that cached controller/type metadata is validated against source-file changes. Caching remains enabled in both modes; when disabled, cached schema metadata is trusted until the GraphQLite cache is cleared.

Please also update the README to document:

  • the default relationship with kernel.debug;
  • what enabling and disabling schema.auto_reload actually changes;
  • an override example;
  • that debug-off deployments must clear the GraphQLite cache after schema-related code changes.

The tests should cover at least staging + debug=false and prod + debug=true, including explicit overrides, and verify that only the expected factory mode is configured.

Following kernel.debug is right for almost everyone, but not for a staging server
that runs with debug on and still wants a cached schema, or for a development
setup that runs with debug off and still wants its edits picked up.

The option defaults to %kernel.debug%, so nothing changes unless it is set, and
the README explains what each setting does and when the cache has to be cleared.
@Mir-Zairan

Copy link
Copy Markdown
Author

Thank you for the proposal. Let me share my throughts on the topic.

I think using kernel.debug as the default is the right direction, but it would be useful to keep schema reloading independently configurable.

Could we expose an option like this?

graphqlite:
    schema:
        auto_reload: '%kernel.debug%'

This would preserve the proposed behavior by default while allowing applications to override it - for example, staging with debug enabled but schema caching retained, or a debug-off development environment that should still detect schema changes.

auto_reload should mean that cached controller/type metadata is validated against source-file changes. Caching remains enabled in both modes; when disabled, cached schema metadata is trusted until the GraphQLite cache is cleared.

Please also update the README to document:

  • the default relationship with kernel.debug;
  • what enabling and disabling schema.auto_reload actually changes;
  • an override example;
  • that debug-off deployments must clear the GraphQLite cache after schema-related code changes.

The tests should cover at least staging + debug=false and prod + debug=true, including explicit overrides, and verify that only the expected factory mode is configured.

Done. Added schema.auto_reload defaulting to '%kernel.debug%', following the same shape as Twig's own auto_reload. The README has a Schema caching section covering the default, what each setting changes, an override example, and clearing the cache on debug-off deploys. Tests cover staging with debug off, prod with debug on, and both explicit overrides, asserting the other mode is not configured. Thanks for your valuable suggestion!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants