This is about my Day 1 development workflow with Postgres: the tools I reach for to build and ship features. I'm not covering Day 2 operations like backup, monitoring, or performance tuning in production. This is the everyday loop instead. Spin up a local database, write some queries, manage schema changes, run tests. These are the tools that live in my development environment and carry me from idea to deployed feature.
Running Postgres Locally
I'm on a Mac, and my current go-to for local Postgres is StackBricks. It supports multiple Postgres versions and other database engines beyond Postgres. Under the hood it spins up Docker containers, which gives you isolation.
I used DBngin before that, which gives a similarly smooth experience with a lightweight UI for managing local database instances.
And before those two, I was a long-time Postgres.app user. Postgres.app is dead simple: download, click, and you have Postgres running natively. To be honest, I also think it has the best icon among all the Postgres tools.
SQL Editor
For writing and running SQL queries, I use TablePlus. It has an elephant logo, but it actually supports a wide range of databases beyond Postgres: MySQL, Redis, SQLite, and more.
I can't point to one killer feature that makes TablePlus stand out. It's more that everything just feels smooth and easier to use than the alternatives. Part of that is because it's built with native Mac AppKit instead of web tech. You can feel the difference in responsiveness and in how it integrates with macOS. But really, it's all those small details adding up.
Schema Migration
For schema migrations, my choice depends on the stack. With Go backends, I use golang-migrate. It's straightforward: write SQL migration files, run them up or down. No magic, just SQL.
When I'm on Node, I prefer Drizzle. The main selling point for me is that Drizzle can export the full schema. That's handy for keeping a copy of my latest database schema in the repo, so I can understand the current state without piecing it together from a stack of migration files.
That said, I think schema migration tooling for Postgres has a long way to go. Most tools follow the imperative pattern: you hand-write a series of ALTER TABLE statements. That's the itch I built pgschema to scratch, a Postgres-specific declarative solution. You define what you want your schema to look like, and the tool figures out the migrations needed to get there. It's still early, but it solves a real pain I keep hitting.
Running Integration Tests
Integration tests often need a real Postgres database.
For Node applications, I use Testcontainers. It spins up Docker containers on-demand during the test run and tears them down afterward. It supports all the mainstream Postgres versions.
For Go applications, I use embedded-postgres. Instead of going through Docker, it downloads and runs a Postgres binary directly. That saves the cost and complexity of Docker: tests start faster, and it's one less dependency to manage.
Type Safety
For Go applications, I use sqlc to generate type-safe code from SQL queries. You write the SQL, sqlc generates the Go code with proper types. No ORM overhead, just type-safe database access.
For TypeScript applications, I pair the database layer with Zod to enforce runtime type validation. This catches type mismatches between your database schema and your application code before they blow up in production.
For Tool Builders
As a Postgres tool builder, I lean heavily on libpg_query to parse PG statements. Most developers won't ever need it, but I want to give it a special shoutout. It's a real differentiator for Postgres compared with other database engines. It hands tool developers reliable parsing, and reliable parsing is the cornerstone of building strong tooling.
Data Seeding
This is the one area where I don't have a settled toolkit yet. I've used Faker.js before to generate realistic test data, but it never stuck as part of my regular workflow. Most of the time I just end up writing quick SQL scripts or custom seed files per project.
I haven't found something that feels as smooth as the rest of the tools in this article. If you have a data seeding approach that actually works, I'd genuinely love to hear it.
That's my current Postgres development toolkit. It keeps evolving. What's working for you?