---
title: "Deploy Postgres + Flanger"
description: "Postgres 18 with Flanger, which drops page cache it isn't using"
category: "Storage"
url: https://railway.com/deploy/postgres-flanger
---

# Deploy Postgres + Flanger

Postgres 18 with Flanger, which drops page cache it isn't using

**[Deploy Postgres + Flanger on Railway](https://railway.com/template/postgres-flanger)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/postgres-flanger/manifest.json

- **Creator:** Kobe Housen's Projects
- **Category:** Storage

## Template content

### postgres

- **Image:** ghcr.io/housek/flanger-postgres:18

## Documentation

# Deploy and Host Postgres + Flanger with Railway

Postgres 18 that bills less memory. This is Railway's own Postgres image (`postgres-ssl:18`, same `wrapper.sh`, SSL, volume layout and variables as the stock Postgres template) with **Flanger** as the entrypoint. Flanger watches which cached file data Postgres re-reads and drops the rest.

## About Hosting Postgres + Flanger

Railway bills a service's memory as the kernel counts it, and that count includes the **page cache**: table and index files Postgres has read stay cached and billed after the workload stops touching them. After a backup, a bulk load or a one-off report, a database can sit at several times the memory it needs.

Flanger drops that cache at a pace bounded by the disk's measured IO headroom, and backs off when what it dropped comes back. Postgres starts first and keeps running whatever Flanger does. Signals are passed through, so a redeploy is a clean `database system is shut down`, not crash recovery. Only file cache is touched, never Postgres memory: dropped cache is re-read from the volume if needed, and dirty pages are never dropped.

Measured on Railway on 2026 Oct 26 with `pgbench -i -s 10` (a 157 MB database), 10 minutes after the load:

| | value |
|---|---|
| memory billed at peak, during the load | 574 MB |
| memory billed 10 minutes later | 180 MB |
| page cache still held | 13 MB |
| evicted | 174.5 MB |
| re-read from disk afterwards | 0.23 MB (0.13 %) |

What remains is mostly Postgres's own `shared_buffers`, which Flanger never touches. Your saving depends on your workload: data that is re-read all the time stays cached.

Those are short-term figures. Over 19 hours on the same mostly idle database, memory held at about 160 MB with almost no page cache, but Flanger evicted 615 MB and the disk read 640 MB in that time. So it was mostly re-reading small catalog files it had just dropped, about 10 KB/s. That is harmless to a quiet database and costs no extra memory, but it is wasted work, and a fix is in progress.

## Common Use Cases

- Databases whose memory bill stays high after nightly backups, `pg_dump` runs or bulk imports
- Databases larger than their working set, where most of the data is rarely read
- Small and side-project databases where page cache is a large share of the bill

## Dependencies for Postgres + Flanger Hosting

- A Railway volume mounted at `/var/lib/postgresql/data` (included in this template)

### Deployment Dependencies

- Image: `ghcr.io/housek/flanger-postgres:18`, rebuilt automatically whenever Railway's `postgres-ssl:18` base image changes, after tests and a start/stop check pass
- Base image: [Railway's Postgres SSL image](https://github.com/railwayapp-templates/postgres-ssl)

### Implementation Details

Variables match Railway's Postgres template: `DATABASE_URL` (private network), `DATABASE_PUBLIC_URL` (TCP proxy), `PGHOST`, `PGPORT`, `PGUSER`, `PGPASSWORD`, `PGDATABASE`, `POSTGRES_*`, `PGDATA`.

Optional switches:

- `FLANGER_DRY_RUN=1`: log what would be evicted, evict nothing.
- `FLANGER_OFF=1`: kill switch, plain Postgres behaviour.
- Without a restart, from a shell in the service: `echo live > /dev/shm/flanger-mode` (or `dry-run`, `pause`).

Flanger logs one JSON line per event on stderr: `start`, `roots`, and a periodic `summary` with `usage`, `file`, `evicted_total` and `reread_total`.

## Reporting an issue

If something looks wrong, open your service's logs on Railway and paste these into your report:

- the `event="start"` line and the `event="roots"` line from the start of the log
- the last few `event="summary"` lines
- any `event="warning"` or `event="backoff"` lines near the problem

They contain versions, sizes, rates and data-folder paths, and no passwords or query contents, but read them before sharing. Set `FLANGER_OFF=1` to run plain, in case you need the problem gone first.

## Why Deploy Postgres + Flanger on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying Postgres + Flanger on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.


## Similar templates

- [RustFS | (Just Updated) S3 Object Store, Public URL and Keys Set](https://railway.com/deploy/rustfs-or-just-updated-s3-object-store-p) — S3-compatible object store, keys and public URL preset, volume kept
- [TimescaleDB](https://railway.com/deploy/timescaledb-railway-template) — A PostgreSQL-based time-series database for analytics on Railway.
- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.

Open this page in a browser: https://railway.com/deploy/postgres-flanger
