A script-friendly alternative to PGTune

Get sensible PostgreSQL configuration recommendations from a simple GET request. Built for CI, provisioning, and one-liners—no UI required.

Tip: use with curl, wget, or your config management of choice.

Sample response
{
  "settings": {
    "shared_buffers": "8GB",
    "effective_cache_size": "24GB",
    "work_mem": "64MB",
    "maintenance_work_mem": "2GB",
    "wal_buffers": "auto",
    "checkpoint_completion_target": 0.9,
    "default_statistics_target": 100,
    "random_page_cost": 1.1,
    "effective_io_concurrency": 200,
    "max_connections": 200,
    ...
  },
  "warnings": []
}
Deterministic

Same inputs → same outputs. Easy to diff and commit.

Zero deps

Just call the endpoint. Great for cloud-init/Ansible/Terraform.

Human-vetted defaults

Sane recs that won’t shock your cluster.

Quickstart

Fill in your server profile and copy the URL or curl command. The page won’t make network calls—no CORS headaches.

GET URL
https://pgconfig.com/v1/tune
curl
curl -sS "https://pgconfig.com/v1/tune"
wget
wget -qO- "https://pgconfig.com/v1/tune"

Endpoint

GET | POST https://pgconfig.com/api/v1/tune

Returns recommended postgresql.conf settings based on the provided server profile. Use GET with query parameters or POST with a JSON body.

Parameters

NameTypeRequiredDescriptionExample
versionnumberNoPostgreSQL major version17
osenumYeslinux | macos | windowslinux
memory_gbnumberYesTotal RAM in GB32
cpusnumberYesLogical CPU count8
storage_typeenumYeshdd | ssd | networkssd
workloadenumYeswebapp | oltp | warehouse | desktop | mixedoltp
max_connnumberNoTarget max_connections (derived from profile)100
num_disksnumberYesNumber of disks used in the cluster1
backup_methodenumNopg_dump (default) | pg_basebackup | pglogical (or any logical backup)pg_dump
num_replicasnumberNoThe number of active replicas0
db_size_gbnumberYesThe projected size in GB100

Example JSON body (POST)

request.json
{
  "version": 17,
  "os": "linux",
  "memory_gb": 8,
  "cpus": 8,
  "storage_type": "ssd",
  "workload": "webapp",
  "num_disks": 1,
  "db_size_gb": 10
}
GET https://pgconfig.com/api/v1/tune/schema.json

Returns the JSON Schema for the request parameters and response of the /v1/tune endpoint.

Response schema

All values are returned as strings or numbers suitable for postgresql.conf. You can template or write them directly.

JSON Schema
{
  "config": {
    "checkpoint_timeout": duration,
    "checkpoint_completion_target": float,
    "wal_compression": on | off,
    "wal_buffers": size,
    "wal_writer_delay": duration,
    "wal_writer_flush_after": size,
    "shared_preload_libraries": string,
    "track_io_timing": on | off,
    "track_functions": string,
    "max_worker_processes": int,
    "max_parallel_workers_per_gather": int,
    "max_parallel_workers": int,
    "bgwriter_delay": duration,
    "bgwriter_lru_maxpages": int,
    "bgwriter_lru_multiplier": float,
    "bgwriter_flush_after": int,
    "enable_partitionwise_join": on | off,
    "enable_partitionwise_aggregate": on | off,
    "jit": on | off,
    "track_wal_io_timing": on | off,
    "wal_recycle": on | off,
    "max_slot_wal_keep_size": size,
    "archive_mode": on | off | undefined,
    "archive_command": string | undefined,
    "min_wal_size": size,
    "max_wal_size": size,
    "max_parallel_maintenance_workers": int,
    "wal_level": string | undefined,
    "max_wal_senders": int,
    "max_connections": int,
    "superuser_reserved_connections": int,
    "shared_buffers": size,
    "effective_cache_size": size,
    "maintenance_work_mem": size,
    "huge_pages": try | off,
    "default_statistics_target": int,
    "random_page_cost": float,
    "wal_keep_size": size,
    "effective_io_concurrency": int,
    "work_mem": size 
  },
  "warnings": [string] | undefined
}
Example response
{
  "config": {
    "checkpoint_timeout": "15min",
    "checkpoint_completion_target": 0.9,
    "wal_compression": "on",
    "wal_buffers": -1,
    "wal_writer_delay": "200ms",
    "wal_writer_flush_after": "1MB",
    "shared_preload_libraries": "'pg_stat_statements'",
    "track_io_timing": "on",
    "track_functions": "pl",
    "max_worker_processes": 8,
    "max_parallel_workers_per_gather": 2,
    "max_parallel_workers": 8,
    "bgwriter_delay": "200ms",
    "bgwriter_lru_maxpages": 100,
    "bgwriter_lru_multiplier": 2.0,
    "bgwriter_flush_after": 0,
    "enable_partitionwise_join": "on",
    "enable_partitionwise_aggregate": "on",
    "jit": "on",
    "track_wal_io_timing": "on",
    "wal_recycle": "on",
    "max_slot_wal_keep_size": "1GB",
    "archive_mode": "on",
    "archive_command": "/bin/true",
    "min_wal_size": "1GB",
    "max_wal_size": "4GB",
    "max_parallel_maintenance_workers": 2,
    "wal_level": "minimal",
    "max_wal_senders": 0,
    "max_connections": 100,
    "superuser_reserved_connections": 3,
    "shared_buffers": "1GB",
    "effective_cache_size": "3GB",
    "maintenance_work_mem": "256MB",
    "huge_pages": "try",
    "default_statistics_target": 100,
    "random_page_cost": 1.1,
    "wal_keep_size": "3GB",
    "effective_io_concurrency": 200,
    "work_mem": "16MB"
  },
  "warnings": [
    "WARNING this tool not being optimal for very high memory systems"
  ]
}

Examples

OLTP on SSD (32 GB, 8 vCPU)
curl -sS "https://pgconfig.com/api/v1/tune?memory_gb=32&cpus=8&storage_type=ssd&workload=oltp&num_disks=1&num_replicas=0&db_size_gb=1&version=17&os=linux&backup_method=pg_dump"
OLTP on Network Storage (128 GB, 24 vCPU)
curl -sS "https://pgconfig.com/api/v1/tune?memory_gb=32&cpus=8&storage_type=ssd&workload=oltp&num_disks=1&num_replicas=0&db_size_gb=1&version=17&os=linux&backup_method=pg_dump"
Ansible snippet
- name: Fetch PG tuning
  ansible.builtin.uri:
    url: "https://api.example.com/v1/tune?\
      memory_gb={{ ansible_memory_mb.real.total / 1024 }}&\
      cpus={{ ansible_processor_vcpus }}&\
      storage_type=ssd&\
      workload={{ profile }}&\
      num_disks={{ ansible_devices.keys() - 1 }}&\
      num_replicas=2&\
      db_size_gb=100&\
      version=17&\
      os=linux&\
      backup_method=pg_basebackup"
    method: GET
    return_content: yes
  register: pg_tune

- name: Show warnings
  when:
    - pg_tune.json.warnings is defined
    - pg_tune.json.warnings | length > 0
  ansible.builtin.debug:
    var: pg_tune.json.warnings

- name: Write postgresql.conf overrides
  ansible.builtin.copy:
    dest: /etc/postgresql/postgresql.conf
    content: |
      {% for setting in pg_tune.json | ansible.builtin.dict2items %}
      {{ setting.key }} = {{ setting.value }}
      {% endfor %}

Status & Errors

200 OK

JSON payload with recommended settings.

400 Bad Request

Missing/invalid parameters. Returns { "error": "message" }.

500 Server Error

Unexpected failure; retry or report.

Versioning & Stability
  • Current ruleset: v1. Pass version to pin behavior.
  • Idempotent GETs. No rate limits enforced by default (set at deploy).
  • Outputs aim to be conservative and production-safe; always benchmark for your workload.