Guides experiment state transitions: launching, pausing, resuming, ending, shipping variants, archiving, resetting, duplicating, and copying to another project. Covers preconditions, implications for variant assignment and analysis, and the decision framework for when to use each action.\nTRIGGER when: user asks to launch, pause, resume, end, ship, archive, reset, duplicate, or copy an experiment to another project.
Add this skill
npx mdskills install PostHog/managing-experiment-lifecycle@PostHog? Sign in with GitHub to claim this listing.Comprehensive lifecycle state machine with clear implications for variant assignment and analysis decisions.
1---2name: managing-experiment-lifecycle3description: "Guides experiment state transitions: launching, pausing, resuming, ending, shipping variants, archiving, resetting, duplicating, and copying to another project. Covers preconditions, implications for variant assignment and analysis, and the decision framework for when to use each action.\nTRIGGER when: user asks to launch, pause, resume, end, ship, archive, reset, duplicate, or copy an experiment to another project.\nDO NOT TRIGGER when: user is creating an experiment (use creating-experiments), configuring rollout (use configuring-experiment-rollout), or setting up metrics (use configuring-experiment-analytics)."4---56# Managing experiment lifecycle78This skill covers experiment state transitions — what each action does, when to use it, and how it affects variant assignment and analysis.910## State diagram1112```text13draft ──launch──▶ running ──end──▶ stopped ──archive──▶ archived14 │ ▲ │15 pause resume ship_variant16 │ │ (also ends if running)17 ▼ │18 paused (flag inactive, still "running" status)1920Any non-draft state ──reset──▶ draft21```2223## Actions and their implications2425For each action, the two key questions:26271. **Who sees what variant?** (user perspective)282. **Who is in my analysis?** (statistical perspective)2930### Launch (`experiment-launch`)3132Transitions draft → running. Activates the feature flag and sets `start_date`.3334- **Preconditions**: must be in draft, flag needs ≥2 variants with "control" first35- **Pre-launch checklist**: has at least one metric? Variants correct? Flag implemented in code?36- **Variants**: users start being bucketed into variants based on the configured split37- **Analysis**: data collection begins from `start_date`3839No request body needed.4041### Pause (`experiment-pause`)4243Deactivates the feature flag. Users fall back to the default experience (typically control).4445- **Preconditions**: must be running and not already paused46- **Variants**: flag is not returned by `/decide` — no new exposure events recorded47- **Analysis**: no new data while paused, but existing data is preserved. Experiment stays "running".4849No request body. Use `experiment-resume` to reactivate.5051### Resume (`experiment-resume`)5253Reactivates the feature flag after a pause. Users are re-bucketed deterministically into the same variants.5455- **Preconditions**: must be paused56- **Variants**: same assignment as before pause — deterministic bucketing57- **Analysis**: exposure tracking resumes5859No request body.6061### End (`experiment-end`)6263Sets `end_date` and transitions to stopped. The feature flag is **NOT modified**.6465- **Preconditions**: must be running (launched, not already stopped)66- **Variants**: users continue seeing assigned variants (flag stays active)67- **Analysis**: results frozen to data up to `end_date`6869Optional body: `conclusion` ("won", "lost", "inconclusive", "stopped_early", "invalid") and `conclusion_comment`.7071Use this when you want to freeze results without changing what users see.7273### Ship variant (`experiment-ship-variant`)7475Rewrites the feature flag so the selected variant is served to 100% of users.7677- **Preconditions**: must be launched (running or stopped). Cannot ship from draft.78- **Variants**: ALL users see the shipped variant. The flag is rewritten with a catch-all group.79- **Analysis**: if still running, the experiment is also ended (end_date set)8081**Always confirm with the user before shipping** — this permanently rewrites the feature flag.8283Required: `variant_key` (e.g. "test"). Optional: `conclusion`, `conclusion_comment`.8485Returns 409 if an approval policy requires review before the flag change.8687### Archive (`experiment-archive`)8889Hides a stopped experiment from the default list view.9091- **Preconditions**: must be stopped (end_date set)92- **Variants**: no change — flag is unaffected93- **Analysis**: no change — results remain accessible9495No request body. Can be restored by setting `archived=false` via `experiment-update`.9697### Reset (`experiment-reset`)9899Returns an experiment to draft state. Clears `start_date`, `end_date`, `conclusion`, and `archived`.100101- **Preconditions**: must not already be in draft102- **Variants**: flag is left unchanged — users continue seeing assigned variants103- **Analysis**: previously collected data still exists but won't be included in results unless `start_date` is adjusted after re-launch104105No request body.106107### Duplicate (`experiment-duplicate`)108109Creates a copy as a new draft with fresh dates and no results.110111**Important**: always provide a unique `feature_flag_key` different from the original. If the same key is used, both experiments share a flag — changes to one affect both.112113Optional: custom `name` (defaults to "Original Name (Copy)").114115### Copy to project (`experiment-copy-to-project`)116117Copies an experiment into a **different project in the same organization** as a new draft. Use this instead of118`experiment-duplicate` when the copy should land in another project; use duplicate when it stays in the same project.119120- **Preconditions**: source must not use legacy metrics; target project must be in the same organization and you must121 have write access to it. Cannot copy across organizations or regions.122- **What's copied**: name, description, type, parameters, filters, primary/secondary metrics (fresh uuids), stats and123 scheduling config, exposure criteria. **Not copied**: saved-metric references (project-scoped), holdout, exposure124 cohort, dates, results, conclusion.125- **Feature flag**: `target_team_id` is required; `feature_flag_key` is optional. The resolved key is then looked up126 **in the target project**, and the lookup result — not whether you passed the key — decides what happens:127 - **If `feature_flag_key` is omitted**: it defaults to the _source_ experiment's flag key. That key normally128 doesn't exist in the target project, so a new flag with it is created there. (The default can still collide — see129 the next point — so to be safe, pass an explicit key.)130 - **If the resolved key already exists as a flag in the target project**: the copy **shares** that existing flag131 instead of creating one. Both experiments then point at the same flag, so lifecycle ops (ship, pause) on either132 affect both. The existing flag must have ≥2 variants including one keyed `control`, otherwise the call returns 400.133 - **If the resolved key does not exist in the target project**: a new, independent flag is created with that key.134 To guarantee independence, pass a `feature_flag_key` that doesn't already exist in the target.135136**Confirm the source experiment and target project by name before calling** — this writes into a project the user137isn't looking at. The returned experiment (and its id) belongs to the target project.138139## Decision framework140141| Situation | Action | Tool |142| -------------------------------------------------- | ------------------------ | ---------------------------- |143| Draft ready, flag implemented, metrics set | Launch | `experiment-launch` |144| Clear winner, significant results | Ship the winning variant | `experiment-ship-variant` |145| No significant difference after sufficient time | End as inconclusive | `experiment-end` |146| Something wrong, need to stop exposure temporarily | Pause | `experiment-pause` |147| Resume after pause | Resume | `experiment-resume` |148| Experiment ended, ready to clean up | Archive | `experiment-archive` |149| Need to start over with same config | Reset to draft | `experiment-reset` |150| Want a similar experiment with a fresh start | Duplicate | `experiment-duplicate` |151| Want the same experiment in a different project | Copy to another project | `experiment-copy-to-project` |152153## Resolving experiments154155All lifecycle actions require an experiment ID. If you don't have one, load the156`finding-experiments` skill to resolve the user's reference (name, description,157"latest", etc.) to a concrete ID before proceeding.158159## Error handling160161| Error message | Meaning |162| --------------------------------------- | ------------------------------------ |163| "Experiment has already been launched." | Can't launch a non-draft experiment |164| "Experiment has not been launched yet." | Can't end/pause/ship a draft |165| "Experiment has already ended." | Can't end/pause a stopped experiment |166| "Experiment is already paused." | Use resume instead |167| "Experiment is not paused." | It's already active |168| "Experiment is already in draft state." | Nothing to reset |169| "Experiment is already archived." | Already done |170171When you get a 400, explain the situation to the user rather than retrying.172
Full transparency — inspect the skill content before installing.