Open-source project
lesovsky/noisia avatar
lesovsky/noisia

Noisia: a PostgreSQL workload generator that breaks the database on purpose

Harmful workload generator for PostgreSQL

800 stars23 forksGoBSD-3-Clause

At a glance

What is it?
Noisia is a Go tool that applies deliberately harmful workloads to a PostgreSQL instance, from idle transactions and deadlocks to slot bloat, WAL flooding and plan-cache growth, so that failure behaviour and recovery paths can be rehearsed. Every workload has a demo and tuning guide, and the tool states plainly that reckless use will cause problems.
Who is it for?
Noisia fits a team rehearsing how a PostgreSQL instance fails and recovers, whether before an upgrade, before a failover policy is written, or while building runbooks for the failure modes their monitoring will not catch. It does not fit a production instance, and the tool says so.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 52 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The catalogue of ways to break a database

Noisia is a harmful workload generator for PostgreSQL, and the supported workload list is the substance of the project.

Several workloads are about resource exhaustion. idle transactions are active transactions on hot-write tables that do nothing during their lifetime, and the impact table notes they might lead to tables and indexes bloating. failed connections exhaust all available connections so other clients are unable to connect. fork connections execute a single short query in a dedicated connection, leading to excessive forking of Postgres backends. The terminate backends workload terminates random backends or queries using pg_terminate_backend() and pg_cancel_backend(), and the impact table says already established connections could be terminated accidentally.

Two workloads are about lock behaviour. rollbacks are fake invalid queries that generate errors and increase the rollbacks counter, and the impact table marks that one as having no impact. deadlocks are simultaneous transactions where each holds locks that the other wants, also marked as no impact. waitxacts is the nastier one: one holder cycles an ACCESS EXCLUSIVE lock on a single table while a rate-limited manager opens N separate connections that each block on it, described as a flickering staircase of blocked sessions, and unbounded it climbs until max_connections is exhausted and new clients get FATAL: sorry, too many clients already.

The impact table is the part to read, because it distinguishes the workloads that merely degrade a server from the ones that take it down.

The workloads that fill the disk

Three workloads attack storage rather than connections, and they are the ones that end with a PANIC.

slot-bloat uses a single un-consumed physical replication slot, which pins WAL so pg_wal grows without bound, leading to disk full and an instance PANIC. The data never grows and checkpoints keep running, yet the disk still fills. wal-flood uses many parallel UPDATE-churn workers to flood WAL on the primary by raw write rate, driving replication lag and, when recycling or archiving cannot keep up, pg_wal growth toward disk full, and the documentation is careful that this is environment dependent and not guaranteed. bloat-churn has many parallel UPDATE-churn workers outrun a still-enabled autovacuum by raw rate, breaking HOT with an indexed updated_at = now() so that heap and index both bloat, while the untouched table tail keeps VACUUM from truncating the file. That last one is described as the remediable rate-attack counterpart to the xmin horizon holder workload, and the difference matters: after stopping noisia the table is repairable with VACUUM FULL, pg_repack or REINDEX CONCURRENTLY.

There is also backend-killer, where a single session leaks prepared statements and the plan cache grows until the backend is OOM-killed and the whole instance restarts, and a very large plan-size option makes each PREPARE heavy and slow. And tempfiles, where queries sort a seeded dataset larger than work_mem and spill to on-disk temporary files on a default-configured server, with the demonstration that raising work_mem per role or per database makes the same query run in memory and the spill disappears.

The temporary files workload is the cleanest of the set, because it is the one with an obvious fix rather than a recovery procedure.

Running it, and embedding it in your own code

The installation route is a release binary from the releases page, or Docker:

```shell script docker pull lesovsky/noisia:latest docker run --rm -ti lesovsky/noisia:latest noisia --help

code

The library is also usable directly, and the example in the README shows the shape of it. You build a workload config, construct a logger, and run the workload under a context:

go config := waitxacts.Config{ Conninfo: "host=127.0.0.1", Waiters: 10, WaitersRate: 1, ReportInterval: 1*time.Second, LocktimeMin: 5*time.Second, LocktimeMax: 20*time.Second, } ```

The instruction attached to that example is important: always use contexts to avoid an infinite run, and the example does it with a context timeout of four seconds and a deferred cancel. That is the difference between a tool and a hazard, and the disclaimer above it says much the same thing in capitals, with the software provided as is with no cares and no guarantees related to your databases.

The implementation is Go, with the module path github.com/lesovsky/noisia targeting Go 1.25.0. The dependencies are the kingpin command line parser, pgx for the database driver, zerolog for logging, testify for the tests and the testcontainers Go library with its PostgreSQL module, which is what lets the test suite spin up a real database rather than mock one.

The demo guides and what the project expects of you

Each escalating workload has a dedicated document under docs/workloads, and the descriptions of those documents are the clearest statement of intent in the repository.

The backend killer guide covers driving a single backend to OOM and an instance restart, how to cap memory, disable swap and turn up the plan pressure. The slot bloat guide covers filling pg_wal with one forgotten replication slot until the disk is full, with CLI flags, two stand recipes and slot-crash recovery. The WAL flood guide covers flooding WAL with parallel UPDATE-churn workers, and is candid about the environment-dependent contract and the disk-full conditions, and how it differs from slot bloat. The bloat churn guide covers outrunning autovacuum by raw rate, the trio of steps that builds it, the post-stop repair reveal with VACUUM FULL, pg_repack and REINDEX CONCURRENTLY, what to watch with pgstattuple, and how a rate attack differs from the horizon attack. The temporary files guide covers the spill and the headline remediation of raising work_mem.

The framing of every guide is the same: how to build a reliable stand, tune the pressure, read the self-report, and recover afterwards. That is the whole method of the project, and it is worth adopting even if you never run the tool. A failure you have rehearsed is a different failure from one you have only read about.

The impact table also deserves a second look, because it marks deadlocks and rollbacks as having no impact while flagging slotbloat, walflood, backendkiller, failconns, forkconns, idlexacts, tempfiles, terminate and waitxacts as affecting running workloads, in some cases with a disk full or an instance restart. The repository was last pushed to on 2026-09-01, with v0.4.0 in July 2026, v0.3.0 in June and v0.2.0 earlier that month, so the tool is young and the workload set is still growing.

Why a failure generator rather than a load generator

A load generator tells you how the server behaves under more traffic. That is a different question from the one Noisia asks, which is what the server does when it is broken rather than busy.

Every workload in the catalogue is an amplifier of a specific misconfiguration that operators make in real life. idle transactions are what a forgotten transaction in an application leaves behind. A replication slot nobody consumes is what a stale standby leaves behind. Autovacuum that cannot keep up is what a write-heavy table leaves behind. The tool reproduces the symptom, and the symptom is the thing your monitoring has to catch and your runbook has to describe.

The remediation built into each description is the second half of the value. The temporary files workload is described as the remediation demo, because raising work_mem makes the spill disappear and that difference is visible in one run. The bloat churn workload is described as the remediable rate-attack counterpart to the xmin horizon holder, and after stopping the tool the table is repairable with VACUUM FULL, pg_repack or REINDEX CONCURRENTLY. The contrast with the horizon attack, where the bloat is not so easily undone, is exactly the distinction an operator needs before a disk fills at three in the morning.

So the tool is not trying to break your database for the pleasure of it. It is trying to produce a specific, nameable failure that you have already decided how to detect and recover from, in a controlled environment, before the real one happens.

Editorial conclusion

Noisia fits a team rehearsing how a PostgreSQL instance fails and recovers, whether before an upgrade, before a failover policy is written, or while building runbooks for the failure modes their monitoring will not catch. It does not fit a production instance, and the tool says so. Before running it, read the impact table rather than the workload list, because several of the workloads take the instance down rather than merely slowing it, and set up a disposable stand, since the demo guides exist for that reason.

Frequently asked questions

What is Noisia and what does it do to PostgreSQL?

It is a BSD licensed Go tool that applies deliberately harmful workloads to a PostgreSQL instance, including idle transactions, rollbacks, waiting transactions, deadlocks, temporary file spills, backend termination, connection exhaustion, plan-cache growth, replication slot bloat, WAL flooding and bloat churn. Each workload has a demo and tuning guide with recovery steps.

How do I run Noisia?

Download a binary from the releases page, or use Docker with `docker pull lesovsky/noisia:latest` and `docker run --rm -ti lesovsky/noisia:latest noisia --help`. You can also import the Go packages and run a workload under a context, which the documentation says is essential to avoid an infinite run.

Which Noisia workloads can actually take a database down?

The impact table marks several as affecting running workloads. The backend killer grows a session until the OOM killer restarts the instance, slot bloat fills pg_wal until the filesystem is full and the instance panics, and the WAL flood drives replication lag and pg_wal growth toward disk full in a constrained environment. The deadlocks and rollbacks workloads are marked as having no impact.

What is the remediation for the Noisia temporary files workload?

The workload sorts a seeded dataset larger than work_mem so it spills to on-disk temporary files on a default-configured server. Raising work_mem per role or per database makes the same query run in memory, and the spill disappears, which is the headline remediation in the dedicated guide.

How does Noisia use the database it tests against?

It uses pgx as the driver and zerolog for logging, with kingpin for the command line. The test dependencies include testcontainers-go with its PostgreSQL module, so the test suite can start a real database instance rather than a mock, and the workload is defined by a config struct with fields for the connection info, the number of waiters and their rate, the report interval and the lock time bounds.

Official sources

  1. Issues
  2. lesovsky/noisia on GitHub
  3. License: BSD-3-Clause
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/lesovsky-noisia.svg)](https://hysenlabs.com/projects/lesovsky-noisia)

Was this useful?