Skip to main content

DBReduce logo

DBReduce

Give DBReduce a PostgreSQL database and a failing test.
It finds a smaller relational dataset and can reduce its schema while preserving the bug.

PyPI Python 3.10+ License Tests

DBReduce reduces PostgreSQL data while checking that each candidate preserves the original failure identity. It supports output matchers and structured JSON verdicts, keeps oracle writes out of accepted data, and follows both PostgreSQL foreign keys and explicitly configured application relationships.

Quick start

DBReduce supports Python 3.10–3.15 and PostgreSQL 13–18 (the experimental clone backend needs PostgreSQL 15 or later). Use current patched, matching-major pg_dump, pg_restore and psql tools; see the compatibility report.

Install DBReduce as a standalone developer tool:

uv tool install dbreduce
dbreduce --help

uvx dbreduce --help also works without a persistent install. Standard installation remains available with python -m pip install dbreduce. DBReduce itself is Python software, but does not need to be installed in the application's environment or added to its dependencies. The oracle can be Ruby, Java, Go, Node.js, Python, shell, or any other executable.

Then reduce a database with a test that identifies the bug:

dbreduce reduce \
  --database postgresql://localhost/app_bug \
  --oracle 'uv run pytest tests/test_checkout.py::test_negative_total' \
  --match-stdout 'AssertionError: negative total' \
  --confirm 3

The oracle must connect through DATABASE_URL or DBREDUCE_DATABASE_URL. DBReduce sets both variables to its disposable workspace for every run. Use a database role with CREATEDB permission. The source database is read only; reductions and oracle executions run against a generated copy. Use trusted commands and dumps: SQL functions, triggers, and external services can have effects outside that copy.

For an oracle that can report a stable signature directly, use --oracle-json and have it write {"reproduced": true, "signature": "checkout-negative-total"} to stdout. Structured oracles can also explicitly report {"reproduced":false,"outcome":"candidate_invalid"} when schema/data removal violates declared application preconditions. DBReduce rejects it separately from target-bug disappearance and infrastructure failures. See the candidate-validity contract and guide for details.

Use --oracle-framed-json when the application logs to stdout. Snapshot isolation is the default and works on PostgreSQL 13–18; --candidate-backend clone is an experimental alternative on PostgreSQL 15–18. Both WAL_LOG and FILE_COPY are tested; file_copy_method requires PostgreSQL 18. --restore-jobs N enables parallel archive restores.

Use --reduce-schema for opt-in whole-table schema reduction. It runs after row reduction, checks each proposed removal with the same oracle, and exports only after a fresh logical restore. The default data-only behavior is unchanged. Use --oracle-json or --oracle-framed-json so an application startup error cannot count as the original bug.

What it does

  • Checks failure identity so an unrelated error does not count as reproducing the bug.
  • Isolates each oracle run so its database writes do not affect later candidates.
  • Reduces through real foreign keys and declared single or composite relationships.
  • Reports the final identity, candidate outcomes, timings, and row counts without saving raw oracle output.
  • With --reduce-schema, tries removal of application tables and their automatic dependencies; reports schema object counts and logical SQL size.

Without an identity matcher, legacy mode accepts any nonzero application exit status and prints a warning. Reports claim local irreducibility under attempted relationship-closed transformations only when no validity or unresolved-check barrier prevents it; DBReduce does not promise a global minimum. By default, DBReduce writes dbreduce.min.sql and dbreduce-report.json and never overwrites existing files.

Real-world validation

The opt-in v0.4.0 schema phase was validated with real Wagtail and NetBox application oracles on PostgreSQL 17. Wagtail used generated application noise; NetBox used the public 4.1 demo dataset with the issue condition added:

Wagtail #9208
Rows:             150,706 -> 3
Tables:           48 -> 1
Failure identity: preserved
Fresh SQL restore: PASS
NetBox #17498
Rows:             21,381 -> 2
Tables:           180 -> 4
Failure identity: preserved
Fresh SQL restore: PASS

The v0.5.0 NetBox rerun explicitly classified 70 schema candidates as candidate_invalid through declared table preconditions, with zero infrastructure errors. It retained the same four tables and two rows. These validity barriers prevent a claim of local irreducibility. NetBox validation exercised its form path, not a full HTTP flow. Earlier results remain documented in the case reports.

See the real-world validation report and case studies for commands, environment, performance numbers, and limitations.

Ruby/Rails validation uses Mastodon #37059: 1,757 rows become two; optional schema reduction leaves 12 of 109 tables. The exported SQL reproduces the same migration exception in v4.5.2 after fresh restore; v4.5.3 returns a negative verdict. With the documented application container and network already set up, the validated oracle command is:

dbreduce reduce \
  --database postgresql://postgres@dbreduce-adoption-pg17/mastodon_case \
  --oracle 'docker exec -e DATABASE_URL="$DATABASE_URL" dbreduce-adoption-mastodon bundle exec ruby /case/wrapper.rb' \
  --oracle-framed-json --confirm 2 --timeout 60

DBReduce runs separately from Rails. The v0.5.0 case records 26 explicitly invalid schema candidates, 524 invalid restores and 24 unresolved oracle infrastructure errors; it does not claim schema local irreducibility.

See CHANGELOG.md for release history.

Documentation

Contributing and reporting

See CONTRIBUTING.md for local setup, checks and contribution guidance. Use the issue templates for bugs and feature requests. Project spaces follow the code of conduct. Report suspected vulnerabilities using the private reporting instructions in SECURITY.md.

Licensed under Apache-2.0.

Metadata

Release files for dbreduce 0.5.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dbreduce 0.5.1
File Size Uploaded Provenance Actions
dbreduce-0.5.1.tar.gz 163.3 kB With provenance Details for dbreduce-0.5.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for dbreduce 0.5.1
File Interpreter ABI Platform Actions
dbreduce-0.5.1-py3-none-any.whl Python 3 none any Details for dbreduce-0.5.1-py3-none-any.whl

Total release size: 216.2 kB

Release files / dbreduce-0.5.1.tar.gz

Download URL dbreduce-0.5.1.tar.gz
Size 163.3 kB
Tags Source
SHA-256 checksum
How to use checksums
7f80f936c4f84d02911e9449217c548285116dd128e78214e68e1eca0aa7ae1f
BLAKE2b-256 checksum
How to use checksums
f073d0988c1ce0a0efd6fc07527c72b81e5c8b0417abf25286206ed81f0a4e58
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

Release files / dbreduce-0.5.1-py3-none-any.whl

Download URL dbreduce-0.5.1-py3-none-any.whl
Size 52.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d2651f77b53fbad3d052c2bf3e23c324906c15917fb177d9801389844b7c8631
BLAKE2b-256 checksum
How to use checksums
52f2d866031f02fc92d86be2cff5da1d296413b9e7e86c9a1677106de6bd8fd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

Security for dbreduce 0.5.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for dbreduce-0.5.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page