# database_cleaner: Ruby database cleaning strategies for test suites

> Database Cleaner is a set of Ruby gems that reset database state between tests, split per ORM and database. The core gem ships strategies; each adapter is a separate gem, and the README is explicit that the fastest option is not always the one you can use.

**DatabaseCleaner/database_cleaner** — Strategies for cleaning databases in Ruby.  Can be used to ensure a clean state for testing.

- Repository: https://github.com/DatabaseCleaner/database_cleaner
- Website: https://www.rubydoc.info/github/DatabaseCleaner/database_cleaner
- Stars: 2,966 · Forks: 485
- Language: Ruby
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/databasecleaner-database-cleaner

## What database_cleaner actually solves in a Ruby test suite

Tests that touch a database leak state. An example creates a user, the next example queries for users, and the assertion fails for a reason that has nothing to do with the code under test. Database Cleaner exists to remove that class of failure. The README describes it as a set of gems containing strategies for cleaning your database in Ruby, and names the original use case: ensuring a clean state during tests.

The audience is narrow and specific. This is for Ruby projects whose tests talk to a real database, whether through ActiveRecord, Sequel, Mongo, Mongoid or Redis. It is not a data anonymisation tool, not a production maintenance utility, and not something you run against a live database. The name is generic enough that search results for it are polluted with WordPress plugins and desktop cleaning apps; the gem itself has nothing to do with any of those.

The design decision worth noting up front is the split into a core gem plus per-ORM adapters. The README states that instead of using the database_cleaner gem directly, each ORM has its own gem, and that most projects will only need database_cleaner-active_record. That keeps a Redis-only project from pulling in ActiveRecord, but it also means the configuration options you need live in the adapter's README, not the core one.

## The four strategies and how cleaning is triggered

The mechanism is a global strategy setting plus an explicit clean call. You assign a strategy, then call DatabaseCleaner.clean when you want the database reset. The README's minimal example sets DatabaseCleaner.strategy = :truncation and then calls DatabaseCleaner.clean whenever cleaning is needed.

The strategies differ in cost and in what they can see. The :transaction strategy wraps work in a transaction and rolls it back, which the README calls the fastest option for SQL libraries. The :truncation and :deletion strategies remove rows instead. There is also a null strategy that performs no cleaning at all, which the README says can be used with any ORM library and can be selected explicitly by setting the strategy to nil.

Some strategies need setup before the test runs. The README notes that :transaction needs to know to open a transaction, so you call DatabaseCleaner.start at the beginning of a run, or wrap the test in a DatabaseCleaner.cleaning block. That distinction matters when you write a shared configuration: a strategy that needs a start call will silently do nothing useful if you only ever call clean.

Strategies also accept options. The README shows passing only: and except: lists to :truncation, so you can restrict cleaning to a set of tables or exclude specific ones. It also states that the truncation strategy will never truncate your schema_migrations table, which is a deliberate safeguard rather than an oversight.

## Installing the adapter gem and wiring up RSpec

You do not add database_cleaner to your Gemfile. You add the adapter for your ORM. For the common case the README gives this Gemfile entry:

```ruby
# Gemfile
group :test do
  gem 'database_cleaner-active_record'
end
```

After running bundle install, the require path follows the adapter name, not the gem family name. The README's usage example starts with require 'database_cleaner/active_record'.

The README's RSpec example combines two strategies: truncate once before the suite, then use transactions for each example.

```ruby
RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :transaction
    DatabaseCleaner.clean_with(:truncation)
  end

  config.around(:each) do |example|
    DatabaseCleaner.cleaning do
      example.run
    end
  end
end
```

The before(:suite) block sets the per-example strategy and performs a single truncation to start from a known state. The around hook wraps each example in DatabaseCleaner.cleaning, which handles the start and clean calls for you. If your suite uses Capybara for feature specs, the README points to an RSpec with Capybara example, which the excerpt cuts off; the adapter README is where the full configuration lives.

If you use more than one ORM, the README shows loading multiple adapter gems side by side, for instance database_cleaner-active_record together with database_cleaner-redis in the test group.

## Why :transaction stops working once tests use multiple connections

This is the limitation that catches people. The README is direct about it: if you need multiple database connections in your tests, for example when tests run in a different process than your application, the :transaction strategy becomes more difficult to use.

It lists the workarounds and their costs. One is forcing all processes onto the same database connection, a common ActiveRecord hack, but the README reports that this approach has been reported to result in non-deterministic failures. Another is rolling transactions back in the application's process and relaxing the database isolation level so tests can read uncommitted data. The README calls the simpler answer :truncation or :deletion, and labels it easier but slower. That trade-off is the honest summary of the whole project: the fastest strategy is the one with the strictest assumptions.

There is a second gap the README leaves open. It asks whether :deletion or :truncation is faster and answers that it depends on your table structure and what percentage of tables you populate in an average test. It cites a Stack Overflow answer on Postgres truncation speed and then says people report different results, concluding that the best approach is to try all options on your test suite. There is no benchmark table and no default recommendation. If you want a number for your schema, you have to produce it yourself.

Finally, the adapter list has a discontinued section. database_cleaner-data_mapper, database_cleaner-couch_potato, database_cleaner-mongo_mapper, database_cleaner-moped and database_cleaner-neo4j are all listed there. If your ORM appears on that list, this project is the wrong tool and the README does not offer a replacement.

## database_cleaner versus Rails transactional fixtures

The real alternative for most Rails teams is not another gem. It is Rails' own transactional fixtures, which wrap each test in a transaction and roll it back without any extra dependency. The difference in approach is scope and control. Transactional fixtures give you exactly one strategy, the transaction rollback, and no way to switch it per test or fall back to truncation for the cases where a transaction cannot see the data.

Database Cleaner's value shows up precisely at that boundary. The README's RSpec example is the shape of the answer: truncate once before the suite, then run transactions per example. That combination is not something transactional fixtures express, because you cannot ask them to do a one-time truncation and then change behaviour. The same applies to the only: and except: table lists, and to the null strategy for suites that need cleaning disabled in a specific context.

The cost of that control is configuration. You now own a strategy choice, a start or cleaning wrapper, and an adapter gem whose options live in a separate README. For a small suite that never leaves a single connection, transactional fixtures are less code and fewer moving parts. Database Cleaner earns its place when the suite has outgrown that assumption.

## Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-06-01. That is roughly four months before today, so the project is not dormant by the six-month measure, but the README does not publish a release cadence and no recent releases were retrieved. Treat version drift as something you check rather than something you assume.

The licence is MIT, stated in the repository and present as a LICENSE file at the top level. MIT is permissive: it allows use, modification and redistribution with the licence and copyright notice retained. That is a description of the terms, not legal advice, and your organisation's own policy decides whether it is acceptable.

The upgrade cost is structural rather than incidental. Because the gems are split per ORM, an upgrade means tracking the core gem and each adapter gem you use, and the adapter README is where the configuration options are documented. The README also notes that some adapters are discontinued, which means an ORM migration can leave you without a cleaning strategy. The repository layout includes a Gemfile, a Rakefile, a docker-compose.yml and a spec directory, so the project tests itself, but nothing in the README promises a migration path between major versions. Pin your adapter versions and read the adapter README before bumping.

## Conclusion

Adopt database_cleaner if your Ruby test suite hits a real database and you need a clean slate per example, and you can install the adapter gem that matches your ORM. Do not adopt it if your tests already run inside a single rolled-back transaction managed by Rails fixtures, or if you use an ORM whose adapter is on the discontinued list. Before wiring it in, verify three things: which adapter gem exists for your ORM, whether your tests use more than one database connection, and whether :transaction or :truncation is faster on your schema. The README's own advice is to try all options on your test suite and see.

## FAQ

### Which database_cleaner gem should I install for ActiveRecord?

The README says most projects will only need database_cleaner-active_record, added to the test group of your Gemfile. The require path in the usage example is database_cleaner/active_record. If you use several ORMs, the README shows loading multiple adapter gems in the same group.

### Is database_cleaner still maintained?

The repository is not archived and the last push was on 2026-06-01. The README does not state a release cadence, and no recent releases were retrieved, so check the adapter README and your pinned versions before upgrading.

### Does the truncation strategy delete the schema_migrations table?

No. The README states that the truncation strategy will never truncate your schema_migrations table.

### Which strategy is fastest?

For SQL libraries the README says the fastest option is :transaction, because transactions are simply rolled back. Between :deletion and :truncation it declines to pick a winner, saying results depend on table structure and advising you to try all options on your own test suite.

## Sources

- [DatabaseCleaner/database_cleaner on GitHub](https://github.com/DatabaseCleaner/database_cleaner)
- [Issues](https://github.com/DatabaseCleaner/database_cleaner/issues)
- [License: MIT](https://github.com/DatabaseCleaner/database_cleaner/blob/main/LICENSE)
- [Project website](https://www.rubydoc.info/github/DatabaseCleaner/database_cleaner)
- [README](https://github.com/DatabaseCleaner/database_cleaner/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/databasecleaner-database-cleaner
