Skip to content

Per-environment settings

Goal: make one codebase behave correctly on every environment: the right values per environment, secrets handled safely, and PHP tuned where the platform allows it.

A Cloud Platform application runs the same codebase on every environment, so anything that must differ between Dev, Stage, and Prod has to come from outside the code. There are three surfaces for that: environment variables, the environment’s PHP settings, and conditional logic in settings.php.

  • settings.php logic that branches on the platform’s own environment variables.
  • Custom variables for your per-environment values, with secrets kept out of them.
  • PHP settings tuned per environment where the platform allows it, defaults left alone elsewhere.
  • A Cloud Platform application and interface access (variables and PHP settings are set there)
  • Ship code to environments, since settings.php changes deploy like any code change
  1. Branch on the platform’s environment variables

    Section titled “Branch on the platform’s environment variables”

    Every environment exposes variables your code and drush commands can read. The ones you’ll actually branch on:

    Variable What it holds
    AH_SITE_ENVIRONMENT The environment name: dev, test, prod, or ide. The environment labeled Stage is named test, so that is the value to compare against
    AH_PRODUCTION / AH_NON_PRODUCTION 1 on the matching side, undefined on the other
    AH_SITE_NAME Site group + environment (used to build absolute paths, e.g. in scheduled jobs)
    AH_SITE_GROUP The site group / Unix user name
    AH_GIT_REF / AH_GIT_SHA The deployed branch/tag name and exact commit hash, for logs and error trackers
    TEMP The environment’s real temp directory (/mnt/tmp/[site].[env]); use it instead of /tmp, which is small and fills

    The full table is in Using environment variables on docs.acquia.com. Typical use in settings.php:

    if (getenv('AH_SITE_ENVIRONMENT') === 'prod') {
    $config['system.performance']['cache']['page']['max_age'] = 43200;
    }

    One ordering rule: Acquia injects platform configuration into settings.php via its own include (the Acquia require line). Environment-variable logic goes after that include, or it can be clobbered by it.

  2. Define custom variables for your own values

    Section titled “Define custom variables for your own values”

    For values you define yourself (an API URL, a feature flag), add custom environment variables per environment with acli:

    Terminal window
    acli api:environments:variable-create myapp.dev --name='MY_VARIABLE' --value='the-value' --task-wait

    variable-list, variable-update, and variable-delete cover the rest of the lifecycle, each taking the same environment ID or alias. Read the value from PHP the way you read a platform one: getenv('MY_VARIABLE'). The Cloud UI has the same actions on the environment; see Creating custom environment variables on docs.acquia.com.

    Rules and quirks worth knowing before you rely on them:

    • Names can’t start with AH or ACQUIA; no spaces, tabs, or quotes in names or values; 255-byte names, 5000-byte values, 100 KB total.
    • They are not a secrets store. Custom variables are unencrypted and can leak into Drupal watchdog logs. Acquia’s own guidance: don’t put SSL certificates, SSH keys, or login/API credentials in them. For secrets, use a file in the private file system read from settings.php, and follow the credential-handling patterns in the auth guide.

    Prefer a custom variable over committed config when the value genuinely differs per environment or shouldn’t live in git history; prefer committed configuration for everything else, so environments stay reproducible from the repository. When whole modules or configuration objects differ per environment rather than single values, that’s a job for a configuration split instead: see manage configuration.

  3. Tune PHP settings where the platform allows

    Section titled “Tune PHP settings where the platform allows”

    acli api:environments:update sets these per environment, one flag each, queuing a task that --task-wait blocks on:

    Terminal window
    acli api:environments:update myapp.dev --memory_limit='192' --task-wait
    • PHP version (--lang_version) per environment. Update Dev or Stage first, verify there, then Prod.
    • PHP memory limit per process (--memory_limit, default 128 MB). Note the split that surprises people: drush and other CLI commands get 512 MB regardless, which is why a memory-starved cron job may succeed via drush and fail via the web. See scheduled jobs.
    • max_execution_time (--max_execution_time, default 300 seconds). Longer isn’t better: a request that needs more than a couple of minutes should become a scheduled job; on Cloud Next, web requests past 10 minutes can be interrupted by routine platform maintenance.
    • OPcache size, APCu size, interned-strings buffer, max input vars, max POST size, memcached memory (--opcache, --apcu, --interned_strings_buffer, --max_input_vars, --max_post_size, --memcached_limit): advanced dials; leave defaults unless Acquia Support advises otherwise or you have measurements. Some upper limits depend on subscription tier; see Configuring PHP settings on docs.acquia.com.

    What you can’t tune: anything at the MySQL server level (centrally managed), Varnish behavior (steered by response headers, not settings), and the web-server configuration itself.

  4. Override settings.php, including the database

    Section titled “Override settings.php, including the database”

    Acquia injects database credentials through its own include; your settings.php never hardcodes them, and after the include runs, $databases is populated. To adjust the connection rather than define it, modify $databases after the include. The supported example: MySQL server variables can’t be changed globally, but can be set per session via connection init_commands:

    // After the Acquia require line.
    $databases['default']['default']['init_commands'] = [
    'isolation' => 'SET SESSION transaction_isolation="READ-COMMITTED"',
    ];

    The same post-include block is where per-environment overrides of any Drupal setting live, guarded by AH_SITE_ENVIRONMENT checks as above. The full set of worked $databases cases (external databases, multisite variants) is in Overriding Drupal $databases settings on docs.acquia.com.

A changed variable isn’t visible

existing SSH sessions don’t see updates (reconnect), and changing a variable re-provisions the environment’s pods, which takes a moment.

An override has no effect

check its position relative to the Acquia require line; platform injection runs in that include, and logic placed before it gets overwritten.

Works via drush, fails via the web (or vice versa)

remember the memory-limit split in step 3.

Was this page helpful?