> For the complete documentation index, see [llms.txt](https://v2.dataos.info/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://v2.dataos.info/concepts/resources/nilus/troubleshooting/postgresql-cdc-partitioned-tables.md).

# PostgreSQL: Partitioned Tables with CDC

Nilus can capture changes from PostgreSQL partitioned tables, but the setup differs slightly from a single-table CDC flow because WAL records are emitted by the physical child partitions that receive the writes.

## How partitioned tables behave

PostgreSQL declarative partitioning lets applications write to a parent table while PostgreSQL routes each row to the matching child partition. For CDC, that means:

* Applications should write through the parent table.
* Change records are produced by the child partitions that store the rows.
* Nilus must be configured with both the parent table and the active child partitions.

## Required setup

1. **Write through the parent table**

* Application writes should target the parent table, not the partition tables directly.

1. **Keep a primary key on the parent**

* Nilus relies on a stable primary key to process updates and deletes correctly.

1. **Include the parent and all child partitions**

* `table.include.list` must include the parent table and every child partition that can receive writes.
* Example:

```yaml
table.include.list: "public.orders,public.orders_2024_q1,public.orders_2024_q2"
```

1. **Use logical replication**

* `wal_level` must be set to `logical`.
* The replication user needs the privileges required to read the listed tables and manage publication state when applicable.

1. **Validate publication coverage**

* Your publication should cover the parent and child partitions, or use a broader publication strategy if that matches your environment.

## Why snapshots look larger than expected

If you include `public.orders` plus two child partitions, Nilus snapshots each listed table. The initial row count therefore reflects the sum of the parent and child tables that you explicitly included.

## Example table layout

```sql
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    customer_id INT,
    created_at DATE NOT NULL
) PARTITION BY RANGE (created_at);

CREATE TABLE orders_2024_q1 PARTITION OF orders FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');
CREATE TABLE orders_2024_q2 PARTITION OF orders FOR VALUES FROM ('2024-04-01') TO ('2024-07-01');
```

## Example Nilus config

```yaml
name: nilus-postgres-partitions
version: v1alpha
type: nilus
spec:
  type: cdc
  compute: universe-compute
  source:
    address: dataos://postgresdepot
    options:
      strategy: flatten
    cdc:
      plugin.name: "pgoutput"
      slot.name: "nilus_slot"
      publication.name: "nilus_pub"
      table.include.list: "public.orders,public.orders_2024_q1,public.orders_2024_q2"
      topic.prefix: "cdc_changelog"
      heartbeat.interval.ms: 60000
  sink:
    address: dataos://testinglh
    options:
      dest_table: pgdb_cdc
      incremental_strategy: append
```

## Best practices

* Keep `table.include.list` in sync with newly created partitions.
* Test snapshot volume and CDC routing before production if partitions are created dynamically.
* Monitor replication slot lag and WAL retention, especially during maintenance windows.
* Keep `topic.prefix`, `slot.name`, and `publication.name` stable once the pipeline is live.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://v2.dataos.info/concepts/resources/nilus/troubleshooting/postgresql-cdc-partitioned-tables.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
