Skip to content

UPDATE of hot row's partition key to archived ts range leaks internal _events table name #21

@imtiazqa

Description

@imtiazqa

When a user UPDATEs a hot row's ts column to a timestamp that falls within an already-archived (cold) partition range, PostgreSQL fails with a partition routing error that exposes the internal _events table name — which the user never created and should never see.

Setup

psql -h localhost -U coldfront -d coldfront

CREATE TABLE coldfront.events (
    id BIGSERIAL,
    ts TIMESTAMPTZ NOT NULL,
    status TEXT,
    payload TEXT
) PARTITION BY RANGE (ts);

ALTER TABLE coldfront.events ADD PRIMARY KEY (id, ts);

CREATE TABLE coldfront.events_p_2026_01
    PARTITION OF coldfront.events
    FOR VALUES FROM ('2026-01-01 00:00:00+00') TO ('2026-02-01 00:00:00+00');

CREATE TABLE coldfront.events_p_2026_06
    PARTITION OF coldfront.events
    FOR VALUES FROM ('2026-06-01 00:00:00+00') TO ('2026-07-01 00:00:00+00');

INSERT INTO coldfront.events (ts, status, payload) VALUES
  ('2026-01-10 10:00:00+00', 'open', 'cold-row-1'),
  ('2026-01-15 14:00:00+00', 'open', 'cold-row-2'),
  ('2026-01-20 09:00:00+00', 'open', 'cold-row-3');

INSERT INTO coldfront.events (ts, status, payload) VALUES
  ('2026-06-10 10:00:00+00', 'open', 'hot-row-1'),
  ('2026-06-12 14:00:00+00', 'open', 'hot-row-2'),
  ('2026-06-15 09:00:00+00', 'open', 'hot-row-3');
\q

Register + Archive

./archiver register \
  --config /tmp/cf-gcs-db.yaml \
  --schema coldfront \
  --table events \
  --period monthly \
  --hot-period "3 months"

./archiver --config /tmp/cf-gcs-db.yaml run

Verify both tiers

psql -h localhost -U coldfront -d coldfront

SELECT relname, relkind FROM pg_class
WHERE relnamespace = 'coldfront'::regnamespace
  AND relname IN ('events', '_events');

SELECT COUNT(*) FROM coldfront._events;           -- expect 3 (hot)
SELECT COUNT(*) FROM coldfront.events;            -- expect 6 (hot + cold)

Reproduce the bug

-- Confirm hot-row-2 exists in hot tier
SELECT ts, status, payload FROM coldfront.events WHERE payload = 'hot-row-2';

-- UPDATE hot row ts to an archived (Jan) range
UPDATE coldfront.events SET ts = '2026-01-25 10:00:00+00' WHERE payload = 'hot-row-2';

<h3 style="color: rgb(191, 191, 191); font-family: -apple-system, &quot;system-ui&quot;, &quot;Segoe UI&quot;, Roboto, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(25, 26, 27); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">Expected vs Actual</h3>
  | Expected | Actual
-- | -- | --
Error message | Clear ColdFront error referencing events | ERROR: no partition of relation "_events" found for row
Internal name exposed | No | Yes — _events leaked
Actionable guidance | Yes | None


Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions