Problem/Motivation

<a href="https://git.drupalcode.org/project/fastly/-/blob/4.0.5/src/CacheTagsHash.php?ref_type=tags#L85-95">CacheTagsHash::getSiteId()</a> currently has fallback behavior that generates and writes the Fastly site ID when no value is already stored.

This makes a read method responsible for persisting configuration. That is a code smell, but in Drupal it is also risky because it can create configuration changes during normal runtime.

Writing configuration from a getter can lead to several problems:

  • Unexpected config writes during cache clears, requests, or CLI commands.
  • Configuration drift between environments.
  • Confusing behavior during configuration export and import workflows.
  • Harder-to-predict setup for multi-environment hosting where each environment must use a distinct Fastly site ID.

The current behavior is also at odds with deployments where the site ID should be decided at install time or provided explicitly through environment configuration.

Steps to reproduce

  1. Install and enable the Fastly module on a Drupal site.
  2. Ensure the Fastly site ID is not already stored in configuration, and do not provide it through environment-specific configuration.
  3. Trigger code paths that call CacheTagsHash::getSiteId(), for example by using functionality that prepares Fastly cache tag invalidation.
  4. Inspect the active configuration after the call.

Expected result: A getter returns an existing value only and does not write configuration.

Actual result: The getter generates a site ID and writes it to storage as a side effect.

Environment: This is especially problematic on platforms with multiple SDLC environments, such as Amazee/Lagoon, where each environment should have its own Fastly site ID to prevent cross-environment cache purges.

Proposed resolution

Move site ID generation out of CacheTagsHash::getSiteId() so the method becomes read-only.

A preferred approach would be:

  • Generate the site ID in hook_install() when config sync is not running.
  • If FASTLY_SITE_ID is available, use it as the primary source.
  • Persist the resolved value during installation so runtime reads do not need fallback writes.

An alternative approach would be to store the value in State API instead of Config if the site ID is considered environment-specific rather than site-specific.

Even with that alternative, the write should still happen during installation or another explicit setup step, not from a getter.

The tradeoff with State API is that database copies between environments could still duplicate the site ID unless environment-specific overrides are in place.

Remaining tasks

  • Refactor CacheTagsHash::getSiteId() so it no longer writes to storage.
  • Add install-time logic to resolve and persist the site ID.
  • Decide whether Config or State is the correct storage location for the site ID.
  • Add test coverage for install-time generation and runtime read-only behavior.
  • Document how FASTLY_SITE_ID should be used for environment-specific setups.

User interface changes

None required if the existing configuration form continues to expose the resolved value correctly.

If follow-up work changes how the site ID is sourced, the help text may need a small update to clarify the precedence between saved configuration and FASTLY_SITE_ID.

API changes

No public API changes are required, but the runtime behavior changes in an important way: calling CacheTagsHash::getSiteId() would no longer mutate storage.

This is a behavioral fix that makes the method safer and more predictable.

Data model changes

Possibly none if the existing configuration key is retained and only the write location changes.

If the site ID is reclassified as environment-specific data, the implementation may need to move the value from Config storage to State API.

Comments

mxr576 created an issue.