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

What an environment is, and telling them apart

An environment is one deployed copy of a site's code, with its own folder, branch and hostnames, over the same database as the site's other environments. What that shares, what it keeps apart, and the calls a template uses to tell which environment it is on.

Who this is for. The developer setting up staging, or writing the first template that must behave differently on production. Afterwards you can say what staging shares with production, and test for the production environment in Smarty and Twig.

The word "environment" means two things on a Core dna project, and most surprises come from mixing them up. On the platform, an environment belongs to a site: a code folder, a branch and some hostnames, sharing the site's database with the site's other environments. Separately, a project can keep a copy of the site on another platform instance, such as a development platform, with a database of its own. This page is about the first; the second is covered under between platform instances.

What an environment is

PartWhat it is
NameFree text typed in the admin: "Production", "Staging", or anything else
Code folderA folder on the server holding this environment's copy of the theme. Its compiled templates, its page cache and its sitemap file are kept there too
Repository and branchThe branch a push deploys into the folder (branches and environments)
HostnamesAny number, one of them the environment's primary hostname
Root recordOptional: a page or a blog that is this environment's home page, so one environment can open on a different page

One environment of each site is the site's primary environment, set on the site record. On a typical site it is production.

The mode, production or development, is not a field of the environment. It comes from a configuration file on the server, .environment.json in the environment's folder or the platform's own default, which Core dna manages. Development mode shows an error on the page with its stack trace, recompiles templates on every request, never stores a page in the page cache and redirects outgoing mail to a development address (the mail check). Production mode stores pages and shows the site's error page instead of the error.

What environments share

Everything in the database. Pages, layouts, components, jobs, forms, menus, redirects, settings, site data, members, orders and payment methods belong to the site or to the account, never to one environment. So staging shows production's content through staging's code, and:

  • Editing on staging edits production. There is one copy of each page.
  • A layout created for work on staging is offered on production at once, pointing at a template path that may exist only in staging's code. Release the template before using the layout on production: until then, a page given that layout fails there, and a component given it renders blank, with no error.
  • An order placed on staging is a real order, through the same payment methods with the same keys. Test a checkout on staging only while every payment method is in Test Mode, or on a separate copy.
  • Jobs react to records, not to hostnames, so a record saved on staging starts the same jobs as one saved on production.

Kept per environment: the code, the compiled templates, the page cache (inside the folder, per hostname), the sitemap file, the search index settings and the mode. That is what staging is for: new code against real content, before it reaches the primary hostname.

Telling environments apart in a template

Every template receives $_currentSite (_currentSite in Twig). These are the calls that describe the environment:

CallReturns
isPrimaryEnvironment()Whether the request is on the site's primary environment: the test for "production"
isPrimaryHostname()Whether the request came in on its environment's primary hostname
isPrimary()Both of the above
isHostnameOfCurrentEnvironment(hostname)Whether a hostname belongs to this environment, ignoring case
getEnvironmentId(), getEnvironmentName()The environment's id and its free-text name
getHostname(), getPrimaryHostname()The hostname record the request matched, and this environment's primary hostname (or null)
getVcsBranch(), getLastVcsHash()The branch this environment deploys, and the first seven characters of the commit in its latest deploy log entry; both empty when there is none

Test with isPrimaryEnvironment(), not with the name or the id. The name is free text that anyone with access to the admin can change, and ids differ from site to site, so a template that compares either breaks when it is copied or the environment is renamed.

Two legitimate uses

Mark and hide everything that is not production. A visible banner stops anyone mistaking staging for the live site, and noindex keeps search engines out of it:

Template code templates/includes/frontend/base-template.html
{if !$_currentSite->isPrimaryEnvironment()}
  <meta name="robots" content="noindex, nofollow">
{/if}
</head>
<body>
{if !$_currentSite->isPrimaryEnvironment()}
  <div class="env-banner" role="note">{$_currentSite->getEnvironmentName()|escape}: {$_currentSite->getVcsBranch()|escape} @ {$_currentSite->getLastVcsHash()}</div>
{/if}
{% if not _currentSite.isPrimaryEnvironment() %}
  <meta name="robots" content="noindex, nofollow">
{% endif %}
</head>
<body>
{% if not _currentSite.isPrimaryEnvironment() %}
  <div class="env-banner" role="note">{{ _currentSite.getEnvironmentName()|e }}: {{ _currentSite.getVcsBranch()|e }} @ {{ _currentSite.getLastVcsHash() }}</div>
{% endif %}

Keep production-only services on production. Analytics, advertising pixels and live chat on staging pollute the client's data and can reach real customers. Load them only on the primary environment's primary hostname:

Template code
{if $_currentSite->isPrimary()}
  {include 'includes/frontend/analytics.html'}
{/if}
{% if _currentSite.isPrimary() %}
  {% include 'includes/frontend/analytics.html' %}
{% endif %}

Both are safe with the page cache, which is kept per environment and per hostname, so a page stored on staging is never served on production. Show content only on production computes the same test once in the base template and shares it with every component.

An environment does not have to be a stage. A production site can run two brands as two environments of one site, sharing their content, with templates that switch on getEnvironmentId(). Ids differ between sites, so assign the comparison once, in one include, and read the result everywhere else.

A copy of the database has a primary environment too

A copy of the site on a development platform carries the same environment records as production, so isPrimaryEnvironment() can be true there. The tests above do not protect a copy: switch production-only services off on the copy itself (the reset checklist).

Go deeper

Was this page helpful?

Your answer goes to the docs team.