partitionDetails

Return one partitioned table with every partition: its bound expression verbatim, whether it is the DEFAULT, whether it is itself partitioned, estimated rows and size (both null, not 0, for a partition never analyzed), and the per-partition live/dead tuples, scan counters and…

read-onlyany connectionsweeps instancesweeps replication groupsweeps group

Synopsis

partitionDetails(schema, table, [limit], [order_by])

Description

Return one partitioned table with every partition: its bound expression verbatim, whether it is the DEFAULT, whether it is itself partitioned, estimated rows and size (both null, not 0, for a partition never analyzed), and the per-partition live/dead tuples, scan counters and vacuum and analyze timestamps. Those statistics are the reason this exists: autovacuum runs per PARTITION, so a parent has no vacuum state of its own and ranking parents finds nothing while one child falls behind.

Bounds are returned verbatim rather than parsed -- a bound carries whatever types the key columns have, and a misparsed boundary is worse than an unparsed one; for a RANGE parent, comparing the highest upper bound against now() is how to see that next period's partition was never created. counters_since says when the scan counters were last reset, and counters_since_source which view said so: pg_stat_database, or the earliest of the server-wide views where the database carries no reset time, as after crash recovery on PostgreSQL 15 and later.

Returns a clear error naming the relkind if the table exists but is not partitioned. At most limit partitions are returned, 100 by default, with partition_count and partitions_truncated beside them: on a table partitioned by day each partition costs about 400 bytes, so three years of them is ~430 KB. To find the partition falling behind, rank with order_by=dead_tuples or oldest_vacuum rather than reading them by name.

Parameters

schema requiredstring
table requiredstring
limit optionalinteger
at most this many partitions, 100 by default and at most 10000. partition_count and partitions_truncated say how many there are; the DEFAULT partition is always kept
order_by optionalstring
which partitions are kept and in what order: name (default, the DEFAULT partition last), dead_tuples, mod_since_analyze, oldest_vacuum (never-vacuumed first), or size

Also accepts connection, instance, replication_group, group, role, described once under arguments every tool takes.

Output

One partitioned table and its partitions, at most `limit` of them. An absent extension or a missing grant is reported as {error, hint} instead.

FieldType
counters_sincestring | null
counters_since_sourcestring | null
is_partition_ofstring | null
keystring | null
order_bystring | null
partition_countinteger | null
partitionsarray | null
partitions_truncatedboolean | null
strategystring | null
tablestring | null

Scope

The counters here are each server's own, so members of a replication group legitimately disagree and the answer is their sum, not the primary's copy. Dead tuples and the last vacuum and analyze times describe work that only happens on a primary; on a replica they are noise, not a second opinion.

Example mocked data

Request

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "partitionDetails",
    "arguments": {
      "schema": "shop",
      "table": "events"
    }
  }
}

Result

{
  "table": "events",
  "strategy": "range",
  "key": "RANGE (created_at)",
  "is_partition_of": null,
  "counters_since": "2026-08-01T00:00:00Z",
  "counters_since_source": "pg_stat_database",
  "partition_count": 2,
  "partitions_truncated": false,
  "order_by": "name",
  "partitions": [
    {
      "name": "events_2026_08",
      "schema": "shop",
      "bound": "FOR VALUES FROM ('2026-08-01 00:00:00+00') TO ('2026-09-01 00:00:00+00')",
      "is_default": false,
      "is_partitioned": false,
      "rows": 7340112,
      "size_estimate": 1182990336,
      "n_dead_tup": 20431,
      "last_autovacuum": "2026-09-02T03:11:40Z"
    },
    {
      "name": "events_default",
      "schema": "shop",
      "bound": "DEFAULT",
      "is_default": true,
      "is_partitioned": false,
      "rows": 412,
      "size_estimate": 57344,
      "n_dead_tup": 0,
      "last_autovacuum": null
    }
  ]
}

Invented values on a fictional shop database, shaped by and checked against this tool's output schema. Real output is returned as structuredContent to clients that negotiate MCP 2025-06-18 or later.

See also

listSchemas, listTables, tableDetails, tableStats, largeObjects, listPartitions, listTableStats, tableSize, listTableSizes, listFunctions, functionDetails, listEnums, enumDetails, listTypes, typeDetails, columnHistogram, listExtendedStatistics, listSequences