Patching Supabase Postgres 17.11 vs Sume's 10-attempt webhook budget
Supabase's September 25 Postgres 15.19 and 17.11 releases fix 44 CVEs. A restart can outlast Sume's ten 30-second webhook attempts, so plan a redeliver.

Supabase's changelog lists Postgres 15.19 and 17.11 as fixing 44 CVEs, dated September 25. If your Sume webhook handler writes to a Supabase database, applying the patch means a restart, and Sume's webhook budget is ten attempts at a default 30 second spacing, so a long enough outage leaves some jobs with a failed delivery even though the jobs themselves finished.
The fix is not to avoid patching. It is to know the budget, keep a polling backup, and use Sume's redeliver endpoint after the window.
The two sets of facts
Supabase facts are from its changelog, read 2026-10-03. Sume facts are from the Webhooks page of the docs.
| Item | Value | Source |
|---|---|---|
| Postgres releases | 15.19 and 17.11 | Supabase changelog |
| CVEs fixed | 44 | Supabase changelog |
| Release date | September 25 | Supabase changelog |
| Automatic webhook attempts | Up to 10 total | Sume Webhooks docs |
| Spacing | Fixed, 30 seconds by default | Sume Webhooks docs |
| Timeout per attempt | 10 seconds | Sume Webhooks docs |
How long the retry window lasts
Ten attempts with 30 seconds between them give nine gaps, about 270 seconds, plus up to 10 seconds of timeout on each attempt if your endpoint hangs rather than refusing at once. That is derived arithmetic from the documented defaults, so a delivery window of roughly five minutes is a fair planning figure. Your own spacing may differ if it was changed.
A Postgres restart that completes inside that window loses nothing, because the next attempt succeeds. One that runs longer exhausts the attempts. The docs say ten refused attempts leave a failed delivery and a job that still reached its real terminal state, so the work is not lost, only the notification.
Recovering after the window
Two recovery paths exist in the docs. Polling GET /v1/jobs/:id/status and then GET /v1/jobs/:id/result works for any job you have an id for. And POST /v1/jobs/{job_id}/webhook/redeliver, which needs jobs:write, re-sends the real terminal event with a fresh timestamp and signature, and does not consume one of the automatic ten.
The receiver should already be idempotent on job_id, as the docs require, so a redelivered event for a job you did record is harmless.
import os
import requests
def redeliver(job_ids):
key = os.environ.get("SUME_API_KEY")
if not key:
raise RuntimeError("SUME_API_KEY is not set")
out = {}
for job_id in job_ids:
r = requests.post(
f"https://api.sume.com/v1/jobs/{job_id}/webhook/redeliver",
headers={"Authorization": "Bearer " + key},
timeout=30,
)
out[job_id] = r.status_code
return out
if __name__ == "__main__":
print(redeliver([]))A maintenance-window plan
- Before the restart, list jobs still
queuedorprocessingwithGET /v1/jobs. - After it, list jobs that completed during the window and are missing from your table.
- Redeliver those, or poll their results, and let the
job_idupsert absorb duplicates. - Schedule patching for a quiet hour so fewer jobs finish mid-restart.
Making the receiver restart-safe
The receiver itself can help. If it cannot reach the database, it should return a non-2xx at once rather than hang, so the attempt is spent quickly and the next one lands closer to recovery. It should never return 2xx before the event is durably stored, because a 2xx ends the retries for that delivery.
Finally, write down the window. If your host publishes expected downtime for a patch, compare it with the roughly five minute retry span, and if the downtime is longer, add the redeliver step to the runbook before the change, not after it.
Sources
Related posts
More in Developers
- Supabase cached egress is $0.03/GB: cost of serving a 20 MB AI clip
Supabase lists cached Storage egress at $0.03 per GB. Worked arithmetic for serving generated clips, and when to link a Sume media URL instead of copying.
- End-user id on jobs: OpenAI safety identifier vs Sume metadata
OpenAI's Realtime guide asks for an OpenAI-Safety-Identifier header. Sume stores caller metadata on the job but does not send it to the provider. Use both.
- Test a faster-and-cheaper claim with your own timings and usage.cost
Luma's news page says Ray3.14 is 4x faster and 3x cheaper. A short Python script turns your own job timings and usage.cost values into two ratios you can trust.
- Text to Dialogue continuity: 100-character context, 3 request IDs
ElevenLabs' Sept 28 changelog adds previous_text and future_text (100 chars max) and request-ID chaining (3 max). A Python limit check.
Written by Sume