Guide 12 · Developer docs

Performance, caching, deployment and go-live

How Core dna caches pages, what makes a render fast, how code reaches a site and what stays behind, the go-live checklist, and running a site once it is live. For developers, leads and site operators who already build pages in a theme repository.

L2–L3
Unit 04 · Environments and what travels between them

Configuration and secrets per environment

Which configuration can differ between a site's environments and which cannot, where secrets belong, and how staging can talk to a partner's sandbox when settings and site data are shared by every environment.

Who this is for. The developer wiring an integration, a payment provider or a mail setting who needs staging and production to behave differently. Afterwards you know which values can differ per environment, who controls each, and where a secret may and may not live.

The environments of a site share one database (what environments share), so most configuration is the same on all of them. Knowing the few places where it can differ saves a lot of "it works on staging".

Where configuration lives

WhatStoredDiffers per environment?Who changes it
Module settings: cache, mail, search, commerce and the restDatabase, saved in the adminNo. One value for the whole account: every site and every environmentAdministrators
Setting overrides.settings.json next to the environment's code, outside gitYes, and it wins over the adminCore dna
Mode and service connections.environment.json in the environment's folder, or the platform's defaultYesCore dna
Site data: keys, URLs and switches your templates readDatabase: a value for one site, or an account-wide value every site falls back toNoAdministrators
Payment methods and their keysDatabase, each method for one site or for every site of the accountNoAdministrators
Tax providers and tax zonesDatabase, per siteNoAdministrators
The theme's own build settingsThe repositoryOnly by branchDevelopers

A setting's value is read in this order, each step overriding the last: the module's default, the value saved in the admin, the signed-in administrator's own value where the setting allows one, and finally .settings.json. The file wins by design, so that an administrator saving a settings page cannot undo an infrastructure decision. It is how one environment gets a different value for a single setting; ask Core dna for the change, because it is not in the repository and a theme cannot set it.

Because module settings are account-wide, a setting changed for one site changes it for every site on the account. Check which sites share the account before you change one.

Where secrets belong

  • Never in the repository, in any branch, for any environment. A key committed once stays in the history; deleting it later does not take it back, and the only fix is to replace the key.
  • Integration keys in site data, read by the template or job that needs them, so the code is identical everywhere and the value is set where the site runs.
  • Provider keys on their records: a payment method's keys are entered on the payment method, a tax provider's on the provider.
  • Never printed into a page. A key a template reads to build a server-side request must not reach the HTML or a script the browser loads. When the browser must call a service, it needs a key made for browsers, such as a provider's publishable key.
  • API credentials for your own integrations belong in the integration's secret store, not in site data the site's templates can read. Prefer an OAuth client; an API key is the older option (Authentication and authorisation).

A sandbox credential on staging

Site data is shared by all of a site's environments, so staging reads production's integration keys unless you arrange otherwise. When staging must talk to a partner's sandbox, store both values under two keys and choose by environment:

Template code
{if $_currentSite->isPrimaryEnvironment()}
  {$crmUrl = $_siteData->get('crm-api-url')}
{else}
  {$crmUrl = $_siteData->get('crm-api-url-sandbox')}
{/if}
{% set crmUrl = _currentSite.isPrimaryEnvironment()
  ? _siteData.get('crm-api-url')
  : _siteData.get('crm-api-url-sandbox') %}

get() returns the value set for this site, or the account-wide value when the site has none, or null. A key read on every page is fetched once per request.

Jobs cannot make this choice. A job reacts to records, which every environment shares, so it has no environment to ask and uses the site's values. A job that must never reach the live partner during testing belongs on a separate copy of the site, with its own site data (between platform instances).

A checklist per environment

  • Which mode it runs in, and therefore whether it stores pages and where its mail goes.
  • Which settings .settings.json overrides on it, as Core dna reports them.
  • Which payment methods are active, and whether each is in Test Mode; which tax provider each zone uses.
  • Which site data keys exist, and which come in a production and a sandbox pair.
  • Which hostnames it answers, and that every environment other than production carries noindex.

Write the answers down with the project's documentation; they are what a new developer, or the client's own team, needs first (the handover pack).

Go deeper

Was this page helpful?

Your answer goes to the docs team.