Provisioning lifecycle

Deep-dive into the environment state machine — all lifecycle states, valid transitions, terminal and non-operational states, and slot accounting.

Every environment in StoreFrame moves through a defined set of lifecycle states. The state machine is the single source of truth for what operations are permitted on an environment and whether a slot is being consumed.

State diagram showing the lifecycle states

Lifecycle states

There are eleven states. They fall into four broad groups.

Transient states (not yet operational)

These states appear during environment setup. The environment is not usable while in any of them.

StateMeaning
draftEnvironment record created; user has not yet paid or confirmed. Checkout may still be in progress.
awaiting_paymentStripe checkout session is open. The environment is waiting for payment confirmation.
provisioningInfrastructure is being created. A background job is building the server stack.
failedProvisioning job encountered an error. The environment may or may not have partial infrastructure.

Active states (operational, slot-consuming)

An environment in any of these states occupies a billing slot.

StateMeaning
trial_activeTrial environment is live. Provisioned on StoreFrame's infrastructure, no subscription required.
activePaid environment is live and running normally.
past_dueSubscription payment failed. Environment continues running during a grace period.

Suspended / expired states

StateMeaning
suspendedManually suspended or grace period exhausted after past_due. The status changes in the Hub; the VM and the store keep running until payment is resolved or the environment is destroyed.
trial_expiredTrial period ended without conversion to a paid plan. No slot consumed.

Terminal states

Once an environment reaches a terminal state it cannot transition further.

StateMeaning
destroyedInfrastructure has been torn down. The environment record is retained for auditing.
archivedSoft-deleted. The record is kept for historical reference; no infrastructure exists.

Valid transitions

The table below lists every permitted state transition. Transitions not in this table are rejected.

FromMay transition to
draftawaiting_payment, provisioning, archived
awaiting_paymentprovisioning, archived
provisioningactive, trial_active, failed
activepast_due, suspended, destroyed, archived
trial_activeactive, trial_expired, suspended, destroyed
trial_expiredactive, destroyed, archived
past_dueactive, suspended, destroyed
suspendedactive, destroyed
failedprovisioning, destroyed, archived
destroyedarchived
archived—

Non-operational states

The four non-operational states are draft, awaiting_payment, provisioning, and failed. When an environment is in any of these states, the Hub redirects to the provision status page rather than showing the environment panel. No Magento access, SSH, or console is available.


How transitions happen

You don't change an environment's state directly. It changes on its own when one of these happens:

  • A job finishes. When a create, destroy, resize or stage job completes, the environment moves to its next state, or to failed if the job did not succeed.
  • A billing event arrives. A failed subscription payment moves the environment to past_due. If payment is not recovered within the grace period, it moves to suspended. A checkout that is never completed expires after 24 hours.
  • A scheduled cleanup runs.
StatusCleaned up after
draft30 minutes
awaiting_payment24 hours (checkout expiry)
failed30 minutes

How customers interact with the state machine

Trial provision

A new trial environment starts at draft, skips awaiting_payment (no payment needed), and moves directly to provisioning via createTrial. On success the background job transitions it to trial_active.

draft → provisioning → trial_active

Convert trial to production

When a trial user subscribes, a new production environment is created and the trial data is synced into it. The trial environment transitions to destroyed independently. The new environment follows:

draft → awaiting_payment → provisioning → active

Fresh project provision

A new paid project (no trial context) opens a Stripe checkout. Once payment is confirmed, provisioning begins:

draft → awaiting_payment → provisioning → active

Stage (child environment)

A Stage is created under an existing active production environment. It follows the same flow as a fresh project but uses a stage slot:

draft → awaiting_payment → provisioning → active

Resize

Resize is only available on active environments. The lifecycle status does not change — the environment stays active throughout. A background job applies the new server type and then broadcasts completion.

Destroy

An active environment (or a failed one) can be destroyed. The background job tears down infrastructure and transitions the environment to destroyed. A production environment cannot be destroyed if it still has child Stage environments.

active → destroyed

Subscription payment failure

When Stripe reports a failed payment the environment moves to past_due. If payment is recovered (card updated, invoice paid) it returns to active. If the grace period expires, it moves to suspended. Reactivation from suspended requires payment recovery followed by a manual or automated reactivation flow.

active → past_due → active  (payment recovered)
active → past_due → suspended  (grace expired)
suspended → active  (reactivated)

Slot accounting

Each environment occupies one slot of its type while in a slot-consuming state.

Slot types

Environment typeSlot typePrice
trialTrialFree
productionProject€50/mo
staging, develop, testStage€10/mo

Slot-consuming states

A slot is consumed whenever an environment is in provisioning, trial_active, active, or past_due. All other states — including failed, suspended, trial_expired, destroyed, and archived — do not consume a slot.

This means a failed provision releases the slot so a retry does not require a subscription change. A suspended environment also releases its slot; the slot is only re-occupied once the environment is reactivated and moves back to active.

Slot reconciliation

Slot counts are reconciled with Stripe at every state transition that enters or leaves a slot-consuming state. The Stripe subscription is updated to reflect the new slot count before the transition is committed.


When transitions fail

If an background job fails after the transition has been written to the database, the environment enters failed. From failed, two paths are available:

  • Retry transitions back to provisioning and a new background job runs
  • Destroy transitions to destroyed and cleans up any partial infrastructure

See /troubleshooting/provisioning-failed for how to diagnose and resolve stuck or failed provisions.

On this page