Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pgspy

A transparent PostgreSQL proxy for developers. Point your app at pgspy instead of your real database and get a live terminal dashboard of every query, its duration, and automatic N+1 warnings — with zero code changes.

┌─ pgspy ─────────────────────────────────────────────────────────────┐
│ pgspy  127.0.0.1:15432 → 127.0.0.1:5432    connections: 2          │
├─────────────────────────────────────────────────────────────────────┤
│ #    │ Time            │ Dur   │ Conn │ Flag      │ Query           │
│ 42   │ 14:23:15.001    │ 2ms   │ #0   │           │ SELECT * FROM u │
│ 43   │ 14:23:15.003    │ 1ms   │ #0   │ N+1 x3    │ SELECT * FROM p │
│ 44   │ 14:23:15.004    │ 1ms   │ #0   │ N+1 x4    │ SELECT * FROM p │
│ 45   │ 14:23:15.183    │ 87ms  │ #1   │           │ SELECT count(*) │
├─────────────────────────────────────────────────────────────────────┤
│ avg 22.8ms   total 4560ms   N+1 warnings: 2                        │
└─────────────────────────────────────────────────────────────────────┘

Why pgspy?

ORM-heavy applications silently generate N+1 queries that tank performance under real load. Framework-specific tools (Rails Bullet, Django Debug Toolbar) don't help if you use Prisma, Sequelize, SQLAlchemy, JOOQ, or raw queries. pgspy works at the TCP level — it is language- and framework-agnostic.

Installation

npm install -g pgspy

Or run directly without installing:

npx pgspy

Usage

Start pgspy:

pgspy --listen 127.0.0.1:15432 --upstream 127.0.0.1:5432

Then change your DATABASE_URL to use port 15432:

# Before
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb

# After
DATABASE_URL=postgresql://user:pass@localhost:15432/mydb

Your app connects through pgspy transparently. The TUI opens automatically.

Options

Flag Default Description
--listen 127.0.0.1:15432 Address pgspy listens on
--upstream 127.0.0.1:5432 Real PostgreSQL address

Keyboard shortcuts

Key Action
q / Ctrl+C Quit
j / ↓ Scroll down
k / ↑ Scroll up
G / End Jump to newest query
g / Home Jump to oldest query
c Clear query list

How N+1 detection works

pgspy normalizes each query by replacing all literal values (strings, numbers) with placeholders and groups identical patterns within a 500 ms window. If the same normalized query appears 3 or more times, it is flagged as an N+1 pattern and all matching queries are highlighted.

Example: these three queries are all SELECT * FROM posts WHERE user_id = ? and trigger a warning:

SELECT * FROM posts WHERE user_id = 1
SELECT * FROM posts WHERE user_id = 2
SELECT * FROM posts WHERE user_id = 3

Duration color coding

Color Meaning
Green < 20ms
Yellow 20–99ms
Red ≥ 100ms

Protocol support

pgspy handles both the simple query protocol (Q messages) and the extended query protocol (P — Parse messages), so it works with prepared statements and connection poolers like PgBouncer.

SSL connections: pgspy intercepts SSLRequest and responds with N (no SSL), then continues in plaintext. This is intentional for local development. Do not use pgspy in production.

License

MIT

About

Transparent PostgreSQL proxy with a live query dashboard, query timing, and N+1 detection for application development.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages