PhoenixKit.Migrations.Postgres.V137 (phoenix_kit v1.7.165)

Copy Markdown View Source

V137: Email event deduplication indexes + aws_message_id backfill, plus optional performance indexes for the emails module (phoenix_kit_emails).

Event dedup

The PhoenixKit.Modules.Emails.Event schema declares unique constraints that the database never enforced (a schema↔DB mismatch). This adds the two partial unique indexes that back them, deduping at the DB level — at-least-once SQS delivery and racing pollers could previously insert duplicate events:

  • single-occurrence types (delivery / bounce / complaint / send / reject / delivery_delay / subscription / rendering_failure / queued): one row per (email_log_uuid, event_type).
  • multi-occurrence types (open / click): one row per (email_log_uuid, event_type, occurred_at), so a recipient's repeated opens and distinct link clicks are kept while an exact SQS redelivery (identical timestamp) is collapsed.

Pre-existing duplicates are removed first so the unique indexes can be created. phoenix_kit_email_events has no bigint id (dropped in V74); uuid is the UUIDv7 primary key and is time-ordered, so MIN(uuid) per group is the earliest row — it is kept, the rest deleted.

email_log_uuid is the canonical FK (NOT NULL, backfilled and FK-constrained in V56/V70; the legacy bigint email_log_id was dropped in V74).

aws_message_id backfill

The hot SQS lookup now relies solely on the dedicated indexed aws_message_id column (the legacy headers-JSONB scan was removed in the app code). Backfill it for any legacy rows whose AWS MessageId lives only in the headers JSONB. DISTINCT ON (aws_id) + a NOT EXISTS guard keep it safe against the existing partial unique index on aws_message_id.

Optional performance indexes

pg_trgm substring-search indexes for the admin email list (pg_trgm is enabled from V111), per-template open/click analytics composites, and a partial index for the archiver's body-compression scan.

Summary

Functions

Drops the V137 indexes. The aws_message_id backfill is data-only and harmless to keep, so it is not reversed.

Functions

down(opts)

Drops the V137 indexes. The aws_message_id backfill is data-only and harmless to keep, so it is not reversed.

up(opts)