Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
bagelhole avatar

Postgresql

  • 125 installs
  • 44 repo stars
  • Updated May 22, 2026
  • bagelhole/devops-security-agent-skills

PostgreSQL (skill) is a Claude Code skill that administers PostgreSQL databases, covering replication, backups, performance tuning, and client authentication.

About

This skill administers PostgreSQL databases in development and production. A developer uses it to configure streaming replication, run pg_dump and pg_basebackup backups, tune postgresql.conf, and set up client authentication. It also covers monitoring queries for connections, long-running queries, and table bloat.

  • Streaming replication and point-in-time recovery setup
  • postgresql.conf tuning for memory, WAL, and planner
  • pg_dump/pg_basebackup backup and restore workflows

Postgresql by the numbers

  • 125 all-time installs (skills.sh)
  • Ranked #299 of 911 Databases skills by installs in the Skillselion catalog
  • Data as of Jul 28, 2026 (Skillselion catalog sync)
At a glance

postgresql capabilities & compatibility

Capabilities
database · devops
Works with
postgres
Use cases
database · devops
Platforms
Linux
Pricing
Free
From the docs

What postgresql says it does

Administer, optimize, and secure PostgreSQL databases in development and production environments.
SKILL.md
You are setting up streaming replication or point-in-time recovery.
SKILL.md
log_min_duration_statement = 250 # log queries slower than 250 ms
SKILL.md
npx skills add https://github.com/bagelhole/devops-security-agent-skills --skill postgresql

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs125
repo stars44
Last updatedMay 22, 2026
Repositorybagelhole/devops-security-agent-skills

What it does

Administer, tune, back up, and replicate a production PostgreSQL database deployment.

Who is it for?

Engineers running self-managed PostgreSQL who need replication, backups, and tuning.

Skip if: ORM query authoring or application-side schema modeling.

When should I use this skill?

You are configuring PostgreSQL replication, backups, or performance tuning.

What you get

A tuned, replicated, backed-up PostgreSQL deployment.

  • Tuned postgresql.conf
  • Replication setup
  • Backup and restore commands

By the numbers

  • shared_buffers guidance set to ~25% of total RAM
  • logs queries slower than 250 ms via log_min_duration_statement

Files

SKILL.mdMarkdownGitHub ↗

PostgreSQL

Administer, optimize, and secure PostgreSQL databases in development and production environments.

When to Use

  • You need a reliable, ACID-compliant relational database.
  • Your application requires advanced features such as JSONB, full-text search, or CTEs.
  • You are setting up streaming replication or point-in-time recovery.
  • You need to tune an existing PostgreSQL deployment for better throughput.

Prerequisites

  • Linux server (Debian/Ubuntu or RHEL-based) or Docker.
  • Root or sudo access for package installation.
  • Familiarity with SQL fundamentals.

Installation and Setup

# Debian / Ubuntu
sudo apt update
sudo apt install -y postgresql postgresql-contrib

# RHEL / Amazon Linux
sudo dnf install -y postgresql15-server postgresql15-contrib
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql

# Verify
psql --version
sudo systemctl status postgresql

Initial User and Database Setup

# Switch to the postgres system user
sudo -u postgres psql
-- Create an application user
CREATE USER myapp WITH PASSWORD 'strong_password_here';

-- Create the database owned by that user
CREATE DATABASE mydb OWNER myapp;

-- Grant connection privileges
GRANT ALL PRIVILEGES ON DATABASE mydb TO myapp;

-- Connect to the database and set default privileges
\c mydb
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO myapp;

psql Commands Reference

\l              -- list databases
\dt             -- list tables in current database
\d+ tablename   -- describe table with storage info
\du             -- list roles
\x              -- toggle expanded output
\timing on      -- show query execution time
\i file.sql     -- execute SQL from file
\copy           -- fast client-side COPY

Configuration Tuning

Edit /etc/postgresql/15/main/postgresql.conf (path varies by OS and version).

# Connection settings
listen_addresses = '*'
max_connections = 200

# Memory — adjust to ~25% of total RAM for shared_buffers
shared_buffers = 4GB
effective_cache_size = 12GB
work_mem = 16MB
maintenance_work_mem = 512MB

# WAL / write performance
wal_buffers = 64MB
checkpoint_completion_target = 0.9
min_wal_size = 1GB
max_wal_size = 4GB

# Planner
random_page_cost = 1.1          # lower for SSD
effective_io_concurrency = 200  # for SSD

# Logging
log_min_duration_statement = 250   # log queries slower than 250 ms
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
# Reload configuration without restart
sudo -u postgres psql -c "SELECT pg_reload_conf();"

# Some settings (shared_buffers, max_connections) require a full restart
sudo systemctl restart postgresql

pg_hba.conf — Client Authentication

# /etc/postgresql/15/main/pg_hba.conf
# TYPE  DATABASE  USER      ADDRESS         METHOD
local   all       postgres                  peer
host    mydb      myapp     10.0.0.0/8      scram-sha-256
host    all       all       0.0.0.0/0       reject
sudo systemctl reload postgresql

Backup and Restore

Logical Backups with pg_dump

# Plain SQL backup
pg_dump -U myapp -h localhost mydb > /backups/mydb_$(date +%F).sql

# Custom compressed format (recommended)
pg_dump -U myapp -h localhost -Fc mydb > /backups/mydb_$(date +%F).dump

# Backup a single table
pg_dump -U myapp -h localhost -t orders -Fc mydb > /backups/orders.dump

# Restore from custom format
pg_restore -U myapp -h localhost -d mydb --clean --if-exists /backups/mydb_2025-01-15.dump

# Restore plain SQL
psql -U myapp -h localhost -d mydb < /backups/mydb_2025-01-15.sql

Physical Backups with pg_basebackup

# Full base backup (used for PITR and replica seeding)
pg_basebackup -h localhost -U replicator -D /backups/base_$(date +%F) \
  --wal-method=stream --checkpoint=fast --progress --verbose

# Verify the backup
pg_verifybackup /backups/base_2025-01-15

Streaming Replication

Primary Server

-- Create replication user
CREATE USER replicator WITH REPLICATION LOGIN PASSWORD 'repl_secret';
# postgresql.conf on primary
wal_level = replica
max_wal_senders = 5
wal_keep_size = 1GB
# pg_hba.conf on primary
host replication replicator 10.0.0.0/8 scram-sha-256

Replica Server

# Stop PostgreSQL on the replica
sudo systemctl stop postgresql

# Remove existing data directory
sudo rm -rf /var/lib/postgresql/15/main/*

# Base backup from primary
sudo -u postgres pg_basebackup \
  -h 10.0.0.1 -U replicator \
  -D /var/lib/postgresql/15/main \
  --wal-method=stream --checkpoint=fast --progress

# Create standby signal file
sudo -u postgres touch /var/lib/postgresql/15/main/standby.signal
# postgresql.conf on replica
primary_conninfo = 'host=10.0.0.1 port=5432 user=replicator password=repl_secret'
hot_standby = on
sudo systemctl start postgresql

Verify Replication

-- On primary
SELECT client_addr, state, sent_lsn, replay_lsn
FROM pg_stat_replication;

-- On replica
SELECT pg_is_in_recovery();           -- should return true
SELECT pg_last_wal_receive_lsn();
SELECT pg_last_wal_replay_lsn();

Monitoring Queries

-- Active connections by state
SELECT state, COUNT(*)
FROM pg_stat_activity
GROUP BY state;

-- Long-running queries (> 30 seconds)
SELECT pid, now() - query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active'
  AND now() - query_start > interval '30 seconds'
ORDER BY duration DESC;

-- Table bloat and dead tuples
SELECT relname,
       n_live_tup,
       n_dead_tup,
       ROUND(n_dead_tup::numeric / GREATEST(n_live_tup, 1) * 100, 2) AS dead_pct
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;

-- Index usage statistics
SELECT relname, indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan ASC
LIMIT 10;

-- Cache hit ratio (should be > 99%)
SELECT ROUND(
  100.0 * sum(blks_hit) / NULLIF(sum(blks_hit) + sum(blks_read), 0), 2
) AS cache_hit_pct
FROM pg_stat_database;

-- Database size
SELECT pg_database.datname,
       pg_size_pretty(pg_database_size(pg_database.datname)) AS size
FROM pg_database
ORDER BY pg_database_size(pg_database.datname) DESC;

Docker Compose Setup

# docker-compose.yml
version: "3.9"

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: myapp
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb
    volumes:
      - pg_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    command: >
      postgres
        -c shared_buffers=256MB
        -c work_mem=8MB
        -c maintenance_work_mem=128MB
        -c effective_cache_size=768MB
        -c log_min_duration_statement=250
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U myapp -d mydb"]
      interval: 10s
      timeout: 5s
      retries: 5

  pgbouncer:
    image: edoburu/pgbouncer:latest
    restart: unless-stopped
    ports:
      - "6432:6432"
    environment:
      DATABASE_URL: postgres://myapp:secret@postgres:5432/mydb
      POOL_MODE: transaction
      MAX_CLIENT_CONN: 500
      DEFAULT_POOL_SIZE: 40
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  pg_data:
docker compose up -d
psql -h 127.0.0.1 -p 6432 -U myapp mydb

Maintenance Tasks

# Manual VACUUM and ANALYZE
sudo -u postgres psql -d mydb -c "VACUUM ANALYZE;"

# Reindex a bloated index
sudo -u postgres psql -d mydb -c "REINDEX INDEX CONCURRENTLY idx_orders_user_id;"

# Check for unused indexes
sudo -u postgres psql -d mydb -c "
  SELECT indexrelname, idx_scan
  FROM pg_stat_user_indexes
  WHERE idx_scan = 0
  ORDER BY pg_relation_size(indexrelid) DESC;"

Troubleshooting

SymptomLikely CauseFix
FATAL: too many connectionsConnection limit reachedIncrease max_connections or add PgBouncer
Slow SELECT on large tableMissing index or stale statisticsRun EXPLAIN ANALYZE; add index; run ANALYZE
High CPU from autovacuumLarge number of dead tuplesTune autovacuum_vacuum_cost_delay; run manual VACUUM
Replication lag increasingReplica under-provisioned or network bottleneckCheck pg_stat_replication; increase wal_keep_size
could not access file "base/..."Disk full or corrupt data directoryFree disk space; restore from pg_basebackup
FATAL: password authentication failedWrong credentials or pg_hba.conf mismatchVerify pg_hba.conf entries and reload

Related Skills

  • mysql - Alternative relational database
  • database-backups - Automated backup strategies
  • redis - Caching layer to reduce database load
  • planetscale - Managed MySQL-compatible alternative

Related skills

FAQ

Does it cover high availability?

Yes, it walks through primary/replica streaming replication with standby.signal and replication verification queries.

What backup methods are covered?

Logical backups with pg_dump and physical base backups with pg_basebackup for PITR and replica seeding.

Databasesdatabases

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.