Skip to Content
Tares

How do I let an AI SRE look at Postgres tables when investigating slow database queries?

Tares lets an AI SRE see your Postgres data with the postgres connector, which polls a table incrementally and stores one event per new or changed row. A key column such as tenant_id becomes the entity key, so the rows sit in the timeline next to your telemetry. For data that lives behind an API instead of a table, the http_poll connector polls any JSON endpoint on a schedule.

How it works

The Postgres table connector reads your table on the source’s poll interval and keeps a cursor on a column that only ever grows, such as an autoincrement id or updated_at. A cursor on id picks up inserts. A cursor on updated_at also picks up updates.

  • Each new or changed row becomes one event.
  • A label marked primary makes an entity column, such as tenant_id, the key for the row.
  • time_column sets the event time. By default it is the cursor if that is a timestamp, otherwise the ingest time.
  • columns limits which columns Tares pulls. Empty means every column, and the cursor, key and time columns are always included.
  • limit sets how many rows are fetched per poll.
  • The dsn is stored as a secret. The API redacts it and catalog exports omit it.

The connector supports discovery. Given the connection URL, it lists the tables it can see, then reads the chosen table’s columns to propose the cursor and labels.

The HTTP API (poll) connector works the same way for JSON endpoints. It stores one event per item in the reply, and you can reach nested values by dotted name in labels, trigger filters and trigger conditions. Tares makes the calls itself, so you run no script on your side.

Set it up

You need a Postgres reachable from the Tares host. The driver ships with Tares, so there is nothing extra to install.

  1. Start Tares locally if it is not already running:

    tares up
  2. Create the source. Ask a connected agent, for example: use tares to ingest the orders table, keyed by tenant_id. The agent runs discovery, a dry run that fetches sample rows, and then creates the source. In the UI, go to Sources → Add source → Postgres, enter the Connection URL and press Discover. Pick a table, check the proposed cursor, entity key and labels, choose the columns, and save.

  3. Or declare the source yourself, or send the same object to POST /api/sources:

    - name: orders connector: postgres poll: 10s config: dsn: postgresql://user:pass@host:5432/appdb table: orders cursor_column: updated_at columns: id,tenant_id,status,amount,updated_at # empty = every column labels: - { name: tenant_id, field: tenant_id, primary: true } - { name: status, field: status }
  4. Verify. Open the source. Recent events shows rows on the next poll, and Fields reports each column’s coverage. Use it to confirm the key column is reliably present.

  5. If the data you need sits behind an API, add an HTTP API (poll) source instead. Enter the method, URL and credentials if the API wants any, then press Discover. Tares calls the API once, shows the reply and fills in the event fields. Use payload_key to point at the list in the reply and id_field so an item is not stored twice.

With the sources in place, point your agent at the AI SRE guide for how investigations run.

What you get

  • Your application’s source-of-truth rows in the timeline, one event per new or changed row, next to your other sources.
  • An entity key on each row, such as tenant_id, so the data is keyed by who it belongs to.
  • Control over what is read. You choose the table, the columns, the cursor and the rows per poll.
  • A source health view with Recent events and Fields, so you can check what arrives before anyone relies on it.
  • The same pattern for any JSON endpoint through http_poll. It deduplicates by id_field, builds a one-line summary from text_template, and backs off on a 429 or any 5xx, with the wait doubling up to an hour.

When something else fits

  • Use the postgres connector for table data. If the data is only reachable through a service API, use http_poll. It refuses a poll interval under 10 seconds.
  • The postgres connector reads a table on a cursor column that only grows. If a table has no such column, it is not a fit as it stands.

Still stuck? Get help

Last updated on