Bulk renew

Select many certificates at once and submit a single action. The backend fans out individual renewal jobs, tracks per-cert progress, and aggregates the outcome. Idempotency keys prevent double-submission of the same batch; partial failures surface as partial_failure with the failed certs callable out for human attention.

01Why bulk vs individual

  • CA/B Forum shortening. SC-081 (47-day certs) means your renewal cadence goes from every 60–90 days to every 20–30. Bulk actions are how you absorb that volume without clicking a thousand buttons a week.
  • Quarterly audits. "Renew every cert issued before date X" is a common ask — bulk action + filter.
  • Rate-limit planning. A bulk action surfaces the combined zone rate-limit picture before you submit, so you don't blow through a weekly quota halfway through.

02Prerequisites

  • Operator role on the project.
  • Each selected cert has a healthy issuer + auto-renew config (or you're explicitly using bulk-renew to restart a stuck cert).

03Submit a bulk action

  1. Certificates → filter / search to your working set.
  2. Tick the row checkboxes (header checkbox = select all on current page; Select all matching filter for the full set).
  3. Click Bulk renew. A confirmation dialog shows:
    • Selected count.
    • Per-zone rate-limit projection (green / amber / red).
    • Preflight warnings per cert (renewal would break pinned client, policy conflict, etc.).
  4. Confirm. The backend creates a bulk_action record with a SHA-256 idempotency key over the sorted cert-id list.
  5. Track progress under Jobs → Bulk actions.

04Bulk action states

StateMeaning
pendingRecord created, individual jobs being enqueued.
in_progressAt least one job running, at least one still pending.
completedEvery cert renewed successfully.
partial_failureSome succeeded, some failed. See the per-cert breakdown.
failedAll jobs failed (rare; usually a config issue upstream).
cancelledOperator cancelled — in-flight jobs finish but pending jobs are dropped.

05Idempotency

The idempotency key is a SHA-256 of the sorted cert-id list + the action type. Submitting the same set twice within the TTL (24 h by default) returns the original action, not a new one. This protects against accidental double-clicks and race conditions between API callers.

# Same set, submitted twice → second returns the original action ID
curl -X POST $API/bulk-actions \
  -H "Authorization: Bearer $KEY" \
  -d '{"type":"renew","certificate_ids":["a","b","c"]}'
# → {"id":"act_abc","status":"pending"}

curl -X POST $API/bulk-actions -d '…same body…'
# → {"id":"act_abc","status":"in_progress"}   ← same record, updated status

06Per-cert tracking

The bulk-action detail page shows a progress panel with every cert's state. States: pending, succeeded, failed (with error), skipped (e.g. cert already within its renewal window or in a non-renewable state). Atomic MongoDB $inc/$push with $slice keeps the UI counters correct under concurrent worker updates.

07Partial failure handling

When the bulk action finishes in partial_failure:

  • The detail page shows the failed set first, sorted by error class.
  • Each failed cert carries the same error surface as an individual renewal — you can click through to the cert's job detail for logs.
  • Retry the failed set with a single click: the Retry failed button creates a new bulk action scoped to just the failures. This is a new record with a new idempotency key — not a merge into the original.

08Cancel

Click Cancel on an in-progress bulk action. Pending per-cert jobs are dropped; in-flight jobs (already polled by a worker) finish their current attempt and then stop. The action transitions to cancelled once every pending/in-flight job settles.

09Rate-limit pre-check

Before you confirm, the dialog shows a per-zone projection based on the current 7-day rolling issuance count vs. the CA's declared weekly limits (currently 50/week for Let's Encrypt registered-domain bucket). Zones projected to exceed limits are highlighted red with a warning that those certs will be deferred or fail. Consider staggering the batch.

10API

POST /api/v1/projects/{projectId}/bulk-actions
{
  "type": "renew",
  "certificate_ids": ["cert_a", "cert_b", ...]
}

GET /api/v1/projects/{projectId}/bulk-actions/{actionId}
# → {
#     "id":"act_abc",
#     "status":"in_progress",
#     "counts":{"total":12,"succeeded":5,"failed":1,"pending":6},
#     "failures":[ {"certificate_id":"...", "error_class":"network", ...} ]
#   }

11Troubleshooting

Bulk action deferred for rate-limit

CA's weekly quota saturated. Wait for the counter to roll off (shown on the zone page) or split the batch over multiple weeks.

"Duplicate bulk action"

Same cert-id set submitted within 24 h. If you genuinely want a second execution, add or remove one cert from the selection — that changes the idempotency key.

Many certs marked skipped

They were outside their renewal window or in a terminal state. The skip is safe — no work was wasted. Re-run the bulk action with a filter that excludes those certs to keep the counts clean.