Safe Database Migration Patterns
affaan-m/ECC
Rules and examples for safe, reversible schema changes in production: zero-downtime column and index changes, large data backfills and ORM migration workflows.
Rules for writing Django migrations in Saleor that avoid long table locks and stay compatible with zero-downtime rolling deploys.
$ npx skills add saleor/saleor --skill saleor-migrations -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install saleor/saleor saleor-migrations --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/saleor/saleor.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/saleor-migrations .claude/skills/saleor-migrations && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "saleor-migrations" agent skill from https://github.com/saleor/saleor/tree/main/.claude/skills/saleor-migrations into .claude/skills/saleor-migrations/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "saleor-migrations", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/saleor/saleor/tree/main/.claude/skills/saleor-migrationsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add saleor/saleor --skill saleor-migrations -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install saleor/saleor saleor-migrations --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saleor/saleor.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/saleor-migrations .agents/skills/saleor-migrations && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "saleor-migrations" agent skill from https://github.com/saleor/saleor/tree/main/.claude/skills/saleor-migrations into .agents/skills/saleor-migrations/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "saleor-migrations", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add saleor/saleor --skill saleor-migrations -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install saleor/saleor saleor-migrations --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saleor/saleor.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/saleor-migrations .cursor/skills/saleor-migrations && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "saleor-migrations" agent skill from https://github.com/saleor/saleor/tree/main/.claude/skills/saleor-migrations into .cursor/skills/saleor-migrations/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "saleor-migrations", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/saleor/saleor.git --path .claude/skills/saleor-migrations--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add saleor/saleor --skill saleor-migrations -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install saleor/saleor saleor-migrations --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saleor/saleor.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/saleor-migrations .gemini/skills/saleor-migrations && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "saleor-migrations" agent skill from https://github.com/saleor/saleor/tree/main/.claude/skills/saleor-migrations into .gemini/skills/saleor-migrations/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "saleor-migrations", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install saleor/saleor saleor-migrationsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add saleor/saleor --skill saleor-migrations -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/saleor/saleor.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/saleor-migrations .github/skills/saleor-migrations && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "saleor-migrations" agent skill from https://github.com/saleor/saleor/tree/main/.claude/skills/saleor-migrations into .github/skills/saleor-migrations/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "saleor-migrations", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add saleor/saleor --skill saleor-migrations -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install saleor/saleor saleor-migrations --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/saleor/saleor.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/saleor-migrations .opencode/skills/saleor-migrations && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "saleor-migrations" agent skill from https://github.com/saleor/saleor/tree/main/.claude/skills/saleor-migrations into .opencode/skills/saleor-migrations/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "saleor-migrations", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
saleor-migrationsRules for writing Django migrations in Saleor that avoid long table locks and stay compatible with zero-downtime rolling deploys.
Saleor deploys across many pods against one shared Postgres, so a migration that holds a long table lock stalls every pod. The skill keeps locks short by requiring one model and one field change per migration, separating schema from data migrations, avoiding a second alteration of a column an earlier migration already changed, and naming migrations after the actual operation. Unique constraints and indexes are added concurrently, since a plain AddConstraint or AddIndex takes a blocking lock, and invariants such as non-negative balances go into database check constraints.
Backward compatibility is the default: during a rolling deploy, pods on the previous version talk to the already migrated database. New fields must be nullable or carry a db_default, because Django's plain default never reaches the database. Removing a field is staged across three releases, starting with a db_default and then removing the field from the ORM state while the column stays, using SeparateDatabaseAndState.
3 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 782a751. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are python).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Saleor Django Migration Rules loads about 1.6k tokens when it runs. Until then it costs about 60 tokens; SKILL.md has 835 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from saleor/saleor at commit 782a751, republished under its BSD-3-Clause licence (© saleor). 835 words, ~1,602 tokens.
.claude/skills/saleor-migrations/SKILL.md (or your agent's skills folder).Saleor deploys with zero downtime across many pods against a shared Postgres. A migration that takes a long table lock stalls every pod. Follow these rules.
0070_add_payment_gift_card_brand, not 0070_alter_payment_partial_add_db_default for something
else).page migration 0030_slug_translation_unique_constraint) — a plain AddConstraint /
AddIndex takes a blocking ACCESS EXCLUSIVE lock and can stall writes across all pods.CheckConstraint, not just
application logic.During a rolling deploy, pods running the previous minor version talk to the already-migrated
database. Django SELECTs and UPDATEs every column it knows about, so the schema must stay valid
for that old ORM. Making the DB backwards-compatible is the default; changing old code requires
crafting two releases at once — reserve it for cases where nothing else works.
Old pods insert rows without knowing the column, so it must be writable without them:
null=True or a db_default. Plain Django default= is not enough — it lives in Python and never
reaches the database.
Removing a NOT NULL / defaulted column in one step can fail mid-deploy while old and new pods coexist.
db_default (or null=True) so the DB can write the column without the ORM.SeparateDatabaseAndState: state_operations=[RemoveField(...)] and database_operations that
make the column nullable. Old pods still find the column; new pods no longer touch it.migrations.SeparateDatabaseAndState(
database_operations=[
migrations.AlterField(
model_name="sitesettings",
name="automatically_confirm_all_new_orders",
field=models.BooleanField(null=True, blank=True),
),
],
state_operations=[
migrations.RemoveField(
model_name="sitesettings",
name="automatically_confirm_all_new_orders",
),
],
)Keep any legacy enum values / code retained only for migration safety tracked as a removal task with a "remove in X.Y" note.
Avoid unless necessary — a rename is an add plus a remove, so it costs the same three releases.
null=True), and write both old and new fields everywhere the old
one is written, so old pods keep seeing valid data. Add a data migration that backfills the new
field. Note in the upgrade guide that N+1 requires upgrading to this patch release first.null=True from the
new field. De-register the old field per "Removing a field" step 2.Handle "new field is null but old one isn't" while both exist.
Any data migration that reshapes data written by old pods runs twice — once before the new code deploys, once in the next version when the old code is provably gone.
post_migrate sender must be the migration's own app config — a common copy-paste bug is
registry.get_app_config("product") inside an account/order migration.BATCH_SIZE) for internal tuning knobs, not an env var nobody
will set.O(N) vs O(1)); batch related lookups../manage.py makemigrations --merge.db_default, then remove the
field from the ORM via SeparateDatabaseAndState, then drop the column in a later version).db_default — a Python-only default= leaves old pods
unable to insert.post_migrate handler passes its own app config as the sender, and that every data
migration is all-or-nothing rather than aborting partway.manage.py migrate and confirm it applies cleanly.© saleor, BSD-3-Clause. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/saleor-migrations of saleor/saleor.
Open the folder on GitHubat commit 782a751
Saleor Django Migration Rules next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Saleor Django Migration Rules this skillsaleor/saleor | 23k | — | ~1.6k | Automated safety check: Pass | BSD-3-Clause | |
| Safe Database Migration Patternsaffaan-m/ECC | 276k | — | ~3.3k | Automated safety check: Pass | MIT | |
| Profiling Slow API EndpointsPostHog/posthog | 40k | — | ~1k | Automated safety check: Pass | Custom licence | |
| Supabase Postgres Best Practicessupabase/agent-skills | 2.7k | 24 repos | ~808 | Automated safety check: Pass | MIT | |
| Database Migrationagulli/atlas-agents | 579 | — | ~702 | Automated safety check: Pass | MIT | |
| DB ContextSilvioBaratto/optimizer | 176 | — | ~6.4k | Automated safety check: Notes | Custom licence |
affaan-m/ECC
Rules and examples for safe, reversible schema changes in production: zero-downtime column and index changes, large data backfills and ORM migration workflows.
PostHog/posthog
Profiles slow PostHog API endpoints when the main cost is in Postgres or Python.
supabase/agent-skills
Gives the agent Postgres rules to consult before writing or changing tables, queries, indexes, RLS policies or migrations, and when diagnosing slow queries.
agulli/atlas-agents
Safely run database schema migrations. An agent skill from agulli/atlas-agents.
SilvioBaratto/optimizer
Complete knowledge of the optimizer PostgreSQL database: 57 ingestion tables, schema, relationships, live row counts, query patterns, and conventions.
hiromaily/go-crypto-wallet
Database schema and migration workflow. An agent skill from hiromaily/go-crypto-wallet.
saleor/saleor
Benchmarks Django ORM filters in Saleor by generating bulk data, extracting the SQL and running EXPLAIN ANALYZE to check index usage.
saleor/saleor
Commits changes in the Saleor codebase and works through pre-commit hook failures from ruff, mypy, the GraphQL schema check and the migrations check.
saleor/saleor
Generates and splits Django schema migrations for Saleor with manage.py makemigrations, enforcing one new model or one field change per migration file.
saleor/saleor
Run pytest tests with automatic virtual environment activation. Use this skill whenever running tests, executing pytest, or when asked to "run tests", "test…
saleor/saleor
Forward-ports or backports a single PR or branch onto the currently checked-out Saleor branch, handling GraphQL version markers and migration numbering along the way.
saleor/saleor
Checklist for adding, changing, deprecating or removing Saleor GraphQL fields, mutations, enums and webhook event types so the change passes review first time.
Works with
Categories
Rules for writing Django migrations in Saleor that avoid long table locks and stay compatible with zero-downtime rolling deploys. Saleor deploys across many pods against one shared Postgres, so a migration that holds a long table lock stalls every pod. The skill keeps locks short by requiring one model and one field change per migration, separating schema from data migrations, avoiding a second alteration of a column an earlier migration already changed, and naming migrations after the actual operation.
Saleor Django Migration Rules fits situations like: creating or editing a Django schema or data migration in Saleor; removing a field without breaking a rolling deploy; adding a unique constraint or index on a busy table; reviewing a migration for lock risk.
Run `npx skills add saleor/saleor --skill saleor-migrations -a claude-code`. Or copy the skill folder (.claude/skills/saleor-migrations in saleor/saleor) into .claude/skills/saleor-migrations in your project. Claude Code loads it when a task matches its description.
Run `npx skills add saleor/saleor --skill saleor-migrations -a codex`. Or copy the skill folder (.claude/skills/saleor-migrations in saleor/saleor) into .agents/skills/saleor-migrations in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add saleor/saleor --skill saleor-migrations -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/saleor-migrations, .gemini/skills/saleor-migrations, .github/skills/saleor-migrations and .opencode/skills/saleor-migrations in your project.
SKILL.md names no scripts, command-line tools or credentials: Saleor Django Migration Rules is instructions for the agent only. Our summary lists: A Saleor checkout with Django and PostgreSQL.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Saleor Django Migration Rules is published under the BSD-3-Clause licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 1.6k tokens (SKILL.md is roughly 6.4k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Saleor Django Migration Rules: Safe Database Migration Patterns (affaan-m/ECC, 276k stars), Profiling Slow API Endpoints (PostHog/posthog, 40k stars), Supabase Postgres Best Practices (supabase/agent-skills, 2.7k stars) and Database Migration (agulli/atlas-agents, 579 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
saleor (a GitHub organization) maintains it in saleor/saleor, which has 23,428 GitHub stars. The repository holds 8 skills in this directory. The repository was last updated on October 9, 2026.
Source: saleor/saleor on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.