Your question
Hello Team
I would like to ask what stalwart does when it can’t write in the Blob storage, in my case s3, due to it being unreachable. Does it have a WAL where it writes the Blob data until it can write in the Blob again, or does it cache it in memory?
Kind regards
Lukas Hagen
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on
Here is a clear picture of what Stalwart does when S3 is unreachable, based on the actual source code.
What happens when S3 is unreachable
There is no WAL or in-memory buffer. When a blob write (or read) to S3 fails, Stalwart does not buffer the data anywhere. Instead, it propagates the error back up the call stack, and the operation that triggered the write fails.
Retry behaviour built into the S3 backend
Stalwart’s S3 backend (crates/store/src/backend/s3/mod.rs) does implement a limited, per-request retry loop with exponential backoff:
- For both
PUT and GET, if the S3 service returns a 5xx error (server-side / transient), Stalwart waits 2^(attempt) seconds and retries, up to maxRetries times (default: 3).
- A connection error (i.e. S3 is completely unreachable at the TCP level) does not match the retry loop – that triggers an immediate
into_error() and the error propagates immediately.
- Once retries are exhausted, or on non-retryable errors, a
StoreEvent::S3Error is raised.
What that means in practice
- Incoming SMTP messages: If Stalwart cannot store the blob after the retries are exhausted, the SMTP transaction will fail. The sending MTA will receive a transient 4xx error and will retry delivery later according to its own schedule. The message is never silently lost from the sender’s perspective.
- No WAL, no in-memory cache, no disk spool for blob data waiting to be written to S3. The durability guarantee comes from the SMTP retry at the sender side.
- There is an optional
verifyAfterWrite (default true) that issues a HEAD after every PUT to confirm the object is actually readable, with its own retry loop for 404/5xx responses.
Practical recommendation
If your S3 endpoint has intermittent availability, you can increase maxRetries (and tune timeout) in the blob store configuration to give more time for transient outages before the SMTP transaction fails and the burden falls back to the sending server’s queue.
Docs reference: S3-compatible blob store configuration
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong. If you found it useful, mention @helpbot in any reply to ask follow-up questions and the bot will respond again.