PlayableLabs Docs
Developers

Environment Data Sync

Copy one organization's content from production into a lower environment for testing against real data

Develop and staging are normally seeded with synthetic data only. When a tester needs one real customer's actual content — games, playable versions, variants, and assets — in a lower environment to reproduce a bug or verify a fix, the copy-organization tool copies exactly one organization's content across.

This is an internal engineering tool run by the team from a local machine with GCP access — it is not exposed through the dashboard UI or the public API.

What it copies

Content belonging to a single organization: the organization record, games, playable versions, variants, assets (and their folders, collections, tags, and usages), share links, and localizations — plus the matching files in object storage.

What it never copies

Anything user-bearing: accounts, organization memberships and invitations, teams, API tokens, network credentials, integrations, export history, or any logs. User-audit columns on copied rows (who created or last updated a row) are cleared rather than carried across. No other organization's data is ever touched.

Dry run, then apply

Every copy starts as a dry run — the default behavior with no flags needed — which resolves the organization, decides whether it's a fresh copy or a refresh of an organization already present in the target, and prints the full plan (row counts per table, object counts and bytes) without writing anything. Re-running the identical command with --yes (and a --target-env declaring which lower environment you mean) applies exactly that plan. Nothing about the plan changes between the dry run and the real run — only whether it writes.

Re-running the same organization later is always safe: rows are upserted by their existing id, so a re-run refreshes content that changed at the source without duplicating anything, and content removed from the source is left alone in the target rather than deleted.

Safety

The tool is built to fail closed rather than silently do the wrong thing: it refuses to run against a source/target pair that looks swapped or production-shaped on either the database or the object storage side, keeps the source connection strictly read-only, and requires an explicit target-environment declaration before it ever writes. One guard is a warning rather than a refusal: some accounts issue a single object-storage credential across production and dev/staging, so an identical source/target access key alone doesn't block a run — it prints a warning and relies on the bucket-name guards instead.

Full runbook

Every flag, the exact commands for pulling credentials, and the complete list of safety guarantees live in the operator runbook: docs/operations/env-sync/copy-organization.md in the main repository. That repository is private, so the path is given rather than linked — open it from your local checkout.

On this page