{"id":45993632,"url":"https://github.com/mgalgs/django-warmdb","last_synced_at":"2026-02-28T21:00:27.715Z","repository":{"id":334473732,"uuid":"1141514532","full_name":"mgalgs/django-warmdb","owner":"mgalgs","description":"Pre-warmed Postgres database pool for faster `manage.py test`","archived":false,"fork":false,"pushed_at":"2026-01-25T08:04:36.000Z","size":63,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-25T14:04:08.716Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mgalgs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-25T00:32:15.000Z","updated_at":"2026-01-25T08:04:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mgalgs/django-warmdb","commit_stats":null,"previous_names":["mgalgs/django-warmdb"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/mgalgs/django-warmdb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgalgs%2Fdjango-warmdb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgalgs%2Fdjango-warmdb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgalgs%2Fdjango-warmdb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgalgs%2Fdjango-warmdb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mgalgs","download_url":"https://codeload.github.com/mgalgs/django-warmdb/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mgalgs%2Fdjango-warmdb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29951672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T18:42:55.706Z","status":"ssl_error","status_checked_at":"2026-02-28T18:42:48.811Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-28T21:00:08.909Z","updated_at":"2026-02-28T21:00:23.624Z","avatar_url":"https://github.com/mgalgs.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# django-warmdb\n\nPre-warmed Postgres database pool for faster `manage.py test`.\n\n`django-warmdb` keeps a *migrated* template database and a pool of cloned databases. Test runs allocate a ready clone instantly, run tests without running migrations, then recycle the clone back to a pristine state.\n\n## Status\n\nAlpha / prototype.\n\n## How it works\n\n1. `warmdb init` creates a **template** database and runs migrations once.\n2. It creates `N` **clone** databases via Postgres `CREATE DATABASE ... TEMPLATE ...`.\n3. The custom test runner allocates one ready clone (sqlite-backed, concurrency-safe).\n4. On teardown, the clone is dropped and re-created from the template.\n\n## Requirements\n\n- Python **3.10+**\n- Django **\u003e= 3.2**\n- Postgres (only backend supported)\n- Postgres role with permissions to `CREATE DATABASE` and `DROP DATABASE`\n\n## Installation\n\n```bash\npip install django-warmdb\n```\n\n## Usage\n\n1) Enable the app and test runner:\n\n```py\n# settings.py\nINSTALLED_APPS += [\"warmdb\"]\nTEST_RUNNER = \"warmdb.runner.WarmDBDiscoverRunner\"\n```\n\n2) Initialize the pool:\n\n```bash\npython manage.py warmdb init --pool-size 5\n```\n\n3) Run tests:\n\n```bash\npython manage.py test\n```\n\n4) Check status:\n\n```bash\npython manage.py warmdb status\n```\n\n5) Invalidate everything (drop template + clones, remove local sqlite state):\n\n```bash\npython manage.py warmdb invalidate\n```\n\n## State file\n\nState is stored in a local sqlite database:\n\n- `Path(settings.BASE_DIR) / \"warmdb_state.sqlite3\"`\n\nThis makes the state location stable regardless of the current working directory.\n\n## Schema change detection\n\nOn `warmdb init`, we compute a `schema_hash` from:\n\n- all `migrations/*.py` file identities and contents across `INSTALLED_APPS`\n- Django version\n\nOn `manage.py test`, we recompute and fail fast if it differs:\n\n```text\nSchema changed since warmdb init.\nRun: manage.py warmdb invalidate \u0026\u0026 manage.py warmdb init\n```\n\nAdditionally, the runner checks for unapplied migrations on the allocated clone using Django's migration system.\n\n## Development\n\nThis repo uses `uv` for environment management.\n\n```bash\nuv venv --python 3.12 --python-preference=only-managed --seed\nuv pip install -e '.[dev]'\nuv run pytest\nuv run black .\nuv run pre-commit run --all-files\n```\n\nInstall git hooks:\n\n```bash\nuv run pre-commit install\n```\n\n### Integration test (optional)\n\nThere is an opt-in integration test that shells out to an example Django project under `tests/example_project`.\n\nEnable it with:\n\nIf you don't already have Postgres running locally, a quick one-liner using Docker is:\n\n```bash\ndocker run --rm -d --name warmdb-postgres -e POSTGRES_PASSWORD=postgres -p 15432:5432 postgres:16\n```\n\nThen run:\n\n```bash\nexport WARMDB_INTEGRATION=1\nexport WARMDB_PGHOST=localhost\nexport WARMDB_PGPORT=15432\nexport WARMDB_PGUSER=postgres\nexport WARMDB_PGPASSWORD=postgres\nexport WARMDB_PGDATABASE=postgres\nuv run pytest -m integration\n```\n\n## Comparison with similar solutions\n\n### Django built-ins: `--keepdb`\n- `--keepdb` avoids dropping the test database between runs, but **initial creation and migrations** still happen the first time (or when schema changes).\n- `django-warmdb` targets the slow part: **migrate once**, then **clone instantly** for each run.\n\n### `pytest-django`\n- `pytest-django` provides excellent test ergonomics and integrates with `pytest`.\n- It doesn't, by itself, provide a pre-migrated Postgres clone pool. You can combine it with `--reuse-db`/`--create-db`, but schema setup is still typically migration-driven.\n\n### Template DB + custom scripts\nMany teams maintain ad-hoc scripts that:\n- build a migrated template DB\n- clone it before tests\n- drop afterwards\n\n`django-warmdb` packages this pattern into:\n- a standard Django management command (`warmdb init|status|invalidate`)\n- a test runner that integrates with `manage.py test`\n- local sqlite state to support a pool and basic concurrency.\n\n### Postgres features (snapshotting / ZFS / filesystem-level clones)\nSome environments can snapshot and clone Postgres data directories very quickly, but that typically requires infrastructure-level support and operational complexity. `django-warmdb` sticks to standard Postgres `CREATE DATABASE ... TEMPLATE ...`.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgalgs%2Fdjango-warmdb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmgalgs%2Fdjango-warmdb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmgalgs%2Fdjango-warmdb/lists"}