Support ticketing — JIRA HTTP resilience
Support ticketing — JIRA HTTP resilience (TIX-16)
Reference for engineers and operators maintaining outbound support-ticket integrations.
Purpose
Outbound support flows call JIRA Cloud REST (issue create, attachments). Both can return transient 429 (rate limit) or 5xx errors. Serverless handlers retry those responses with backoff so a brief outage does not fail ticket sync on the first attempt.
L1 email (TIX-9) uses SMTP (api/_lib/smtpEmail.ts), not Resend — same SMTP_* vars as KPI alerts and storefront mail.
What is retried
| Client | File | Calls |
|---|---|---|
| JIRA REST | api/_lib/jira.ts | jiraRequest (JSON API), attachFileToJiraIssue (multipart) |
Shared helper: api/_lib/httpRetry.ts → fetchWithRetry.
Retry policy
| Setting | Value |
|---|---|
| Max attempts | 4 (1 initial + 3 retries) |
| Retry when | HTTP 429 or 5xx |
| No retry | 4xx other than 429 (e.g. 401, 404) — fail immediately |
| Backoff | Exponential from 500 ms, cap 8 s, small jitter |
Retry-After | Honoured when JIRA sends the header (seconds or HTTP-date) |
After all attempts are exhausted, the last response is returned. Callers (JiraRequestError) surface a clean failure to logs and support_tickets.jira_sync_error — no infinite loops.
L1 email (SMTP, not retried via httpRetry)
| Env | Purpose |
|---|---|
SMTP_SERVER, SMTP_PORT, SMTP_LOGIN, SMTP_PASSWORD | Gmail/relay auth |
SMTP_FROM_EMAIL, SMTP_FROM_NAME | From header |
SUPPORT_L1_EMAIL or SMTP_LOGIN | L1 inbox (to address) |
sendSmtpEmail tries configured port then 587/465 fallback on network errors.
What is not retried
- Inbound JIRA webhooks (
api/support/jira-webhook.ts) — JIRA redelivers on its side; idempotent inbox handles duplicates. - pg_net queue retries for
/api/support/jira-syncand/api/support/l1-notifyremain separate (DB-level re-queue on handler failure).
Verify locally
npm run test -- tests/api/httpRetry.test.ts tests/api/jiraClient.test.tsOperations
| Symptom | Likely cause | Action |
|---|---|---|
support_tickets.jira_sync_attempts high / sync failing | Sustained JIRA outage or bad credentials | Check Vercel logs for JiraRequestError; verify jira_* / JIRA_* env |
| L1 email missing but ticket created | SMTP misconfiguration or relay blocked | Check SMTP_* env; Vercel may block outbound SMTP on some plans |
| Slow sync after rate limit | Expected — backoff up to ~8 s per attempt | Normal; reduce burst if Atlassian throttles often |
Related docs
- PRD:
docs/specs/ticketing-jira-prd.md— §E8, §Risks & mitigations - Webhook setup:
docs/specs/support-jira-webhook-setup.md - JIRA client:
api/_lib/jira.ts