fix(deliverymq): Add index to attempts_default partition - #1064
samadalishah wants to merge 1 commit into
Conversation
|
For more context: Our default partition already has 30 million rows. Looking into the attempts table, we noticed a particular event was attempted more than the allowed maximum (attempt_max: 6, but attempt_number: 11). This was happening for several events. The root cause was that the Postgres DB was overloaded due to storage I/O saturation. Because the lookup query took more than 30 seconds (and up to 40+ seconds in some instances) and the Redis As a quick fix, we scaled up the DB instance to alleviate the bottleneck. However, we found that adding this index would be a more permanent help. We have already applied this index to our database, but we opened this PR to see what the general stance is for this case. Also, are there any plans to add data cleanup as a feature to Outpost? |
|
Hi @samadalishah, thanks for opening the PR and sharing more context. I'm trying to fully understand the issue. This statement strikes me as a bit odd.
I don't fully follow why this is the case. I'm not sure why this is the behavior, especially "under high I/O load" since I don't fully see how that's related. I'm personally leaning more towards the query itself using Do you have the plan of the query when it used the wrong index by chance? |
Summary
Adds a PostgreSQL composite index on
attempts_defaultto optimize retry execution lookups for the latest attempt by event, tenant, and destination.Context
Retry execution fetches the latest prior attempt from logstore before publishing the next delivery task.
deliverymq-retry task → retry scheduler → fetch latest attempt → execute deliveryThe query filters by:
event_idtenant_iddestination_idand orders by:
time DESCid DESCwith
LIMIT 1.Under high I/O load, PostgreSQL can choose an existing tenant/destination/time index and apply
event_idas a heap filter. In large default partitions, that can require many page reads for a single retry lookup.During an incident, slow Postgres retry lookups contributed to retry tasks running longer than the Redis retry visibility timeout
RETRY_VISIBILITY_TIMEOUT_SECONDS(default 30 secs). That allowed the same retry task to become visible again and increased duplicate retry pressure.Changes
Adds this index:
Operational notes
This index is created only on
attempts_default, which matches the current production table layout.CREATE INDEX CONCURRENTLYis used to avoid blocking writes while the index is built. Building the index can still be I/O intensive on large deployments, so it should be monitored during rollout.Longer term, monthly partitions would make retention and table maintenance safer, since old attempts could be removed by dropping partitions instead of batched deletes.