# Retry and Resilience

Census handles transient API failures automatically using retry with exponential backoff. This ensures reliable operation even under rate limiting or temporary server issues.

## Retry behavior

| Error type | HTTP status | Retry? | Strategy |
|------------|-------------|--------|----------|
| Rate limited | 429 | Yes | Wait `Retry-After` seconds (server-provided) |
| Server error | 500, 502, 503 | Yes | Exponential backoff with jitter |
| Authentication | 401 | No | Fail immediately |
| Quota exceeded | 403 | No | Fail immediately |
| Client error | 400, 422 | No | Fail immediately |

## Rate limiting (429)

The CertiSigma API enforces a sliding window of **1000 requests/minute** per API key. When the limit is hit:

1. The server responds with HTTP 429 and a `Retry-After` header.
2. Census waits exactly the specified duration.
3. The request is retried.
4. After 3 failed retries, the error is raised.

## Server errors (5xx)

For transient server errors:

1. First retry: `base_delay * 2^0 + jitter` (approx. 1.0–2.0 seconds)
2. Second retry: `base_delay * 2^1 + jitter` (approx. 2.0–3.0 seconds)
3. Third retry: `base_delay * 2^2 + jitter` (approx. 4.0–5.0 seconds)
4. Maximum backoff is capped at 120 seconds.

Jitter (random 0–1 second) prevents thundering herd when multiple clients retry simultaneously.

## Configuration

Default values (not currently CLI-configurable, but adjustable in code):

| Parameter | Default | Description |
|-----------|---------|-------------|
| `max_retries` | 3 | Maximum retry attempts per API call |
| `base_delay` | 1.0s | Base delay for exponential backoff |
| `MAX_BACKOFF` | 120s | Maximum wait between retries |

## Incremental saves

To complement the retry logic, the `scan` command saves the manifest **after each batch attestation**. If a scan is interrupted between batches, all previously attested hashes are preserved. Combined with `--resume`, this provides a robust recovery path:

```bash
# Scan interrupted after 300 of 500 batches
census scan /large-dir --source quarterly

# Resume picks up where it left off
census scan /large-dir --source quarterly --resume
```

## Error logging

Failed API calls are logged at ERROR level. With `--log-format json`, these appear as structured JSON for SIEM ingestion:

```json
{"timestamp": "2026-03-18T14:30:00", "level": "ERROR", "module": "cli", "message": "Batch attest failed: CertiSigmaError(502)"}
```

See [logging.md](logging.md) for logging configuration.
