Skip to main content
skill CX Codex

postgresql — Claude Code skill: what it does, how to install

Guides PostgreSQL database administration, streaming replication, backups, and performance tuning. Useful when deploying or optimizing database instances.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill postgresql -a claude-code
Open on GitHub

What postgresql does

This skill provides runbooks and commands for administering PostgreSQL on Debian, Ubuntu, RHEL, or inside Docker Compose. It includes baseline user and database creation scripts alongside essential psql shortcuts. Pre-built SQL queries help track long-running transactions over 30 seconds, calculate table dead tuple bloat, inspect index scans, and check the cache hit ratio.

Performance tuning guidance covers memory allocation for shared_buffers, planner cost adjustments for SSDs, and logging slow queries via log_min_duration_statement. The guide also details client rules in pg_hba.conf, logical dumps with pg_dump, and physical backups using pg_basebackup. For streaming replication, it outlines setup steps on primary and standby nodes using standby.signal.

Package installation requires sudo or root privileges. Modifying shared_buffers or max_connections demands a full PostgreSQL restart, meaning pg_reload_conf() will not suffice for those changes.

What it helps with

  • Configure streaming replication between primary and replica servers
  • Tune memory settings including shared_buffers and work_mem in postgresql.conf
  • Detect active queries running longer than 30 seconds and table dead tuples
  • Create database backups using pg_dump or pg_basebackup
  • Secure client access in pg_hba.conf using scram-sha-256

Example prompts for the agent

  • Help me configure PostgreSQL streaming replication for a standby replica
  • Optimize postgresql.conf for an SSD server and show queries for finding slow transactions
  • Show commands to create a compressed database backup with pg_dump and restore it

How to install postgresql

1Skills CLI (Vercel)

npx skills add BagelHole/DevOps-Security-Agent-Skills --skill postgresql -a claude-code

2Manually: put the files in place

~/.claude/skills/postgresql/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/postgresql/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about postgresql

How to install postgresql in Claude Code?

Run npx skills add BagelHole/DevOps-Security-Agent-Skills --skill postgresql -a claude-code in your terminal.

What does the postgresql skill do?

It guides you through installing PostgreSQL on Linux or Docker, configuring streaming replication, tuning memory settings, and monitoring slow queries.

What are the prerequisites for this skill?

You need a Linux host (Debian, Ubuntu, or RHEL-based) or Docker, root or sudo privileges for package installation, and familiarity with basic SQL.

Source text

SKILL.md · MIT
---
name: postgresql
description: Administer PostgreSQL databases. Configure replication, backups, and performance tuning. Use when managing PostgreSQL deployments.
license: MIT
metadata:
  author: devops-skills
  version: "1.0"
---

# 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

```bash
# 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

```bash
# Switch to the postgres system user
sudo -u postgres psql
```

```sql
-- 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).

```ini
# 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
```

```bash
# 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
```

```bash
sudo systemctl reload postgresql
```

## Backup and Restore

### Logical Backups with pg_dump

```bash
# 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

```bash
# 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

```sql
-- Create replication user
CREATE USER replicator WITH REPLICATION LOGIN PASSWORD 'repl_secret';
```

```ini
# 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

```bash
# 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
```

```ini
# postgresql.conf on replica
primary_conninfo = 'host=10.0.0.1 port=5432 user=replicator password=repl_secret'
hot_standby = on
```

```bash
sudo systemctl start postgresql
```

### Verify Replication

```sql
-- 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

```sql
-- 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

```yaml
# 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:
```

```bash
docker compose up -d
psql -h 127.0.0.1 -p 6432 -U myapp mydb
```

## Maintenance Tasks

```bash
# 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

| Symptom | Likely Cause | Fix |
|---|---|---|
| `FATAL: too many connections` | Connection limit reached | Increase `max_connections` or add PgBouncer |
| Slow SELECT on large table | Missing index or stale statistics | Run `EXPLAIN ANALYZE`; add index; run `ANALYZE` |
| High CPU from autovacuum | Large number of dead tuples | Tune `autovacuum_vacuum_cost_delay`; run manual `VACUUM` |
| Replication lag increasing | Replica under-provisioned or network bottleneck | Check `pg_stat_replication`; increase `wal_keep_size` |
| `could not access file "base/..."` | Disk full or corrupt data directory | Free disk space; restore from `pg_basebackup` |
| `FATAL: password authentication failed` | Wrong credentials or pg_hba.conf mismatch | Verify pg_hba.conf entries and reload |

## Related Skills

- [mysql](../mysql/) - Alternative relational database
- [database-backups](../database-backups/) - Automated backup strategies
- [redis](../redis/) - Caching layer to reduce database load
- [planetscale](../planetscale/) - Managed MySQL-compatible alternative

© devops-skills · MIT · BagelHole/DevOps-Security-Agent-Skills

Similar skills

All skills for DevOps and infrastructure →

From the same set129

prometheus-grafana This skill gives your agent templates for Prometheus scraping, PromQL queries and Grafana panels. Handy when a project needs monitoring added. CX Codex +1 449installs windows-server A skill for Windows Server administration: roles and features, IIS sites, Active Directory users, updates. Useful when the agent touches Windows infrastructure. CX Codex +1 449installs container-hardening Hardens Docker images and runtime environments with non-root users, read-only filesystems, and Kubernetes security contexts. CX Codex +1 433installs vulnerability-scanning A skill for finding and prioritizing CVEs across systems and dependencies with Nessus, OpenVAS, Qualys and Nuclei. Useful for audits and compliance work. CX Codex +1 424installs ssl-tls-management A skill for SSL/TLS work: issuing Let's Encrypt certificates, automating renewal, running cert-manager in Kubernetes and checking cipher suites. Useful when you set up HTTPS or fix an expired cert. CX Codex +1 420installs hashicorp-vault A skill that walks your agent through HashiCorp Vault: secret engines, auth methods, policies and certificate issuance, without guessing CLI syntax. CX Codex +1 413installs backup-recovery Configures backup and disaster recovery strategies using rsync and Restic. Useful for protecting data locally or in AWS S3 and Backblaze B2 following the 3-2-1 rule. CX Codex +1 406installs database-backups A skill that helps your AI agent set up automated backups for PostgreSQL, MySQL and MongoDB, then verify that restores actually work. CX Codex +1 405installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor