中文
Shopify knowledge · Guide

Separating Development, Staging, and Production for a Shopify App

An environment matrix for a Shopify App from local development through integration testing to release, covering how organizations, apps, dev stores, config files, backend resources, secrets, and release permissions should be separated.

Separating environments for a Shopify App usually does not require two organizations. The common approach is to stay in one organization and use different Shopify Apps, different test stores, and different backend resources to carry development, integration testing, and production traffic.

Shopify CLI lets one codebase link to several app configurations, so a named configuration selects the development, staging, or production app. See Manage app config files.

A working environment matrix

EnvironmentShopify AppStoreBackend resourcesPurpose
Local developmentIts own development appThe developer's own dev storeLocal services and a development databaseFast iteration and generating test data
StagingIts own staging appA fixed integration dev storeSeparate domain, database, queues, and secretsPost-merge OAuth, webhook, billing, and regression testing
ProductionThe real appReal merchant storesFully separate production resourcesServing merchants

A dev store is for development and testing only: it can't be used for production, can't process real transactions through live payment providers, and can't be converted into a production store. See Development stores.

What can be shared

  • The same repository and the same core business modules.
  • The same organization and its member management.
  • Reusable deployment templates, database migrations, and test code.
  • Configuration structure that carries no environment-specific values.

What cannot be shared

  • A Shopify App's client ID, secret, and released versions.
  • The app URL, allowed OAuth redirect URLs, and webhook endpoints.
  • Databases, caches, object storage, and job queues.
  • Third-party service credentials and their callbacks.
  • Logs, alerts, audit records, and data retention scope.
  • CI/CD deployment permissions and production approval.
  • The test stores used to verify installation.

Separate apps isolate the Shopify platform identity and nothing else — not your database, and not your deploy permissions. The reverse fails too: separate databases behind a single Shopify App do nothing to stop a test configuration from being released to the production app.

Using config files

One codebase can hold several named configurations:

shopify.app.development.toml
shopify.app.staging.toml
shopify.app.production.toml

Shopify's current documentation provides app config link to create or relink a configuration, app config use to switch the local default, and --config to select a target explicitly for a single command:

shopify app dev --config development
shopify app deploy --config staging
shopify app deploy --config production

Shopify does not require every configuration to be committed: you can commit only the production configuration and gitignore personal development ones. Either way, secrets do not belong in a config file — that is general security practice rather than something Shopify's page spells out. Automation must name its target with --config rather than relying on whatever default a developer set locally with app config use.

Naming stores

Choose names that state the product, environment, and purpose for the store's whole lifetime:

product-dev-carl
product-staging
product-qa-billing
product-demo

A personal dev store can be filled with throwaway data at any time; a fixed staging store should hold a reproducible baseline; a demo or review store should stay tidy so it can be recorded and handed to an outside reviewer. Do not name a dev store prod — it invites the assumption that real transactions run through it.

The path from development to production

  1. Feature branches are verified on a personal dev store.
  2. After merge, deploy the staging backend and release the matching configuration to the staging app.
  3. On the fixed test store, verify installation, authorization, scope changes, webhooks, billing, uninstall, and reinstall.
  4. Keep the evidence and require a human approval for the production release.
  5. Build the same verified code into a production artifact, inject production configuration, and deploy.
  6. When releasing the production app configuration, check scopes, redirect URLs, and extension versions again.

shopify app deploy releases the app configuration and extensions that Shopify hosts; it does not deploy your backend. Hosting the backend — building the app, provisioning a database, setting environment variables, running it somewhere — is a separate process; see Deploy to a hosting service. Backend releases and app configuration releases are two separate pipelines, and each needs its own sign-off.

When two organizations are actually warranted

Two organizations are meaningful only when the organization itself is the boundary:

  • Test and production belong to different legal entities or owners.
  • An outside team may touch test assets but must not join the production organization.
  • Compliance requires organization-level permissions, accounting, and auditing to be fully separate.
  • The development assets will be handed over to another company as a whole.

Otherwise a second organization adds overhead in members, app ownership, stores, and billing, and still does not replace separating backend resources and credentials.

Before going live

  • Every CI command names its Shopify configuration explicitly.
  • Staging and production share no domain, database, or secret.
  • No dev store has the production app installed, and no real merchant store has a development app installed.
  • Redirects, webhooks, and the app home URL all point at the matching environment.
  • Production release requires its own approval, and a developer's local default configuration plays no part in it.
  • OAuth, scope changes, uninstall and reinstall, and billing have each been run for real on staging.

The point of environment separation is not to have more config files. It is that a failed test cannot contaminate production identity, production data, or a merchant's experience.