Limits and retention
How long we keep what, and where the ceilings are.
Retention
| What | How long | Configurable |
|---|---|---|
| Message content | Whatever is set in Settings, in days and in messages | Yes |
| Event timeline | 30 days | No |
| The message row | Kept | No |
| Webhook deliveries | 30 days | No |
| Audit log | Kept | No |
The content has two limits and is kept only while it is inside both: a number of days, and a number of messages. We keep the content of the newest messages up to that number, 50 at most, which is also the default.
There are two because they say different things. Days say for how long and never how much, and how much is what fills a disk: an account sending invoices with a PDF attached can put ten gigabytes a week on it without ever passing seven days. The number of messages is a ceiling in space, and it is also the question support actually gets, which is always about the message that just went out.
Setting the number of messages to zero means keeping nothing once the message has left. If what you send is password resets, one-time codes or magic links, that is what to choose: a stored body is a link that still works for anybody who can read the database.
The deadline in days is stamped on each message when it is created. Changing the setting neither deletes anything you have already sent nor extends what was already marked to go. It is the only way the setting can be predictable: lowering the number must not retroactively delete something somebody needs today. The number of messages is different: lowering it is a request to hold less, and that one applies to what is held.
While it is stored, the content is encrypted in the database. That does not stop us reading it; it stops anybody holding a copy of the database without the key: a backup, a dump. It is why the answer to "what if your database is stolen?" is this and not only the deadline.
When the deadline passes, the message body is deleted and the fact is recorded. The row, the status and the timeline stay, so you can still answer "was this message delivered?" long after the content has gone.
API limits
| Requests per minute, per key | 600 |
| Messages per hour, per account | 2,000 |
| Messages per day, per account | 20,000 |
| Where to see what is left | The panel's summary, GET /v1/me, the headers on every 202 |
Size of a message in raw |
25 MB |
| Recipients per message | 1 |
| Headers per message | no fixed limit, 998 characters each |
Rows per page (limit) |
200, 50 by default |
The 25 MB limit is the one nearly every receiver applies. A larger message would pass here only to be refused there, after it had already spent the attempt.
Suppression limits
| Lines per import | 50,000 |
| File size | 10 MB |
| Addresses on the list | no limit |
Webhooks
| Attempts per event | 7, over ~33 hours |
| Time we wait for an answer | 10 seconds |
| Consecutive failures before disabling | 10 |
| Response stored | first 4 KB |
We keep only the first 4 KB of your endpoint's answer. A broken endpoint returning an HTML error page on every attempt would fill the table without adding anything to the diagnosis.
Where the data lives
All the infrastructure is in the European Union. The panel loads nothing from outside networks: the fonts, the icons and the API reference are served by us, which also means the panel works behind a company proxy that blocks CDNs.
Each account has its own database. It is not a tenant_id column in a shared
table: they are separate databases, which makes it impossible for a badly
written query to return another client's data.
What we do not keep
- Your API key. We keep a hash and the prefix.
- A webhook's signing secret in the clear, once we have shown it to you.
- Message content past the retention deadline.
If you need more
The limits above are the base plan's. If your volume or your retention need different numbers, talk to us: nearly all of them are configuration rather than architecture.