Limits and retries
Design for bounded load and uncertain networks without creating duplicate logical operations.
Public message limits
| Resource | Maximum | Failure |
|---|---|---|
| Complete EML body | 10,485,760 bytes (10 MiB) | 413 payload_too_large |
| Header block | 262,144 bytes (256 KiB) | 422 email_too_complex |
| Header count | 500 | 422 email_too_complex |
| One logical header | 65,536 bytes (64 KiB) | 422 email_too_complex |
| MIME parts | 200 | 422 email_too_complex |
| MIME depth | 20 | 422 email_too_complex |
| Attachments | 50 | 422 email_too_complex |
| Aggregate decoded part data | 10,485,760 bytes (10 MiB) | 422 email_too_complex |
The request format is one complete message/rfc822 body. Media-type parameters are accepted. Omit Content-Encoding or use identity; compressed, JSON, form-data, and base64-wrapped request bodies are not supported.
The server's current total processing budget defaults to 45 seconds and cannot be configured above 120 seconds. Body receipt and parsing are bounded within that total. Configure a client per-attempt timeout above 120 seconds and a separate finite total retry deadline. These are processing bounds, not an SLA or latency guarantee.
Retryable outcomes
Retry network-unknown outcomes and 408, 429, 500, or 503 only with:
- the same idempotency key;
- the same in-memory or immutable message bytes;
- exponential backoff with jitter;
- no more than four attempts as a conservative client starting point;
- a finite overall deadline;
Retry-Afterwhen the response provides it.
Retry-After is optional on 429 and 503; some runtime paths can calculate it and others cannot. Do not invent a zero-delay retry when it is absent.
Permanent outcomes
Do not automatically retry 400, 401, 403, 404, 405, 409, 413, 415, or 422. Correct the request, credential, authorization, path, method, or logical-operation identity first.
409 is only the different-bytes idempotency conflict in public v1. A still-processing original request uses retryable 503 idempotency_in_progress, not 409.
Backpressure and rate limits
Hermes can return 429 for rate, quota, reservation, or concurrency protection. No fixed requests-per-minute, burst allowance, throughput guarantee, or commercial quota is published. Bound your own queue and concurrency. If 429 or 503 rates rise, reduce concurrency instead of opening parallel retry storms.
Controls deliberately not contractual
Worker count, internal admission capacity, Redis timeouts, local fallback size, parser implementation, database leases, providers, and network pinning are implementation controls. They are not public limits or service-level commitments.