When the image service is down, what your recipients see
By Danish Mohammed, founder. 8 min read
When part of the EmailTimer.App image service fails, a recipient sees a picture, not a broken image icon. Every request for an image address answers HTTP 200 with a valid image: the live countdown when it can, and otherwise one of three stand-ins. The one gap is a total outage of the server itself, and the edge Worker that closes it is deployed but not yet routed.
This is the reliability chapter of choosing a dynamic image and countdown timer vendor for an enterprise email programme. It is written for the person who has to answer “what does our campaign look like if you go down”, and it describes the code as it stood on 23 September 2026.
The rule behind it is short. An email has already been delivered when its image is fetched, and nothing can recall it, so an error status is a broken image for good. The service is built so that nothing it controls ever sends one.
The four pictures an image address can return
These are real renders from the product’s own engine, the same sale design in each state, plus the card the image service keeps on disk for failures.
| Picture | Served when | Shared caches keep it | Counts as an open |
|---|---|---|---|
| Live countdown | Everything worked | 30 seconds | Yes |
| Expired frame | The deadline has passed | 7 days | Yes |
| Template fallback | This recipient’s image cannot be drawn, such as a missing per-recipient deadline | 30 seconds | Yes |
| Service card | Bad signature, unknown template, suspended workspace, a rate or concurrency ceiling, a render past 5 seconds, or any exception | 30 seconds | No |
Where each one is set, and how to give a template a fallback image of your own, is on what a timer shows when it is not counting down. This page is about what happens around them during an incident.
The card has two layers under it. If its file were missing from a deployment, the service draws a plain grey card of the same size without fonts or native code, and if even that fails, it sends a one-pixel grey PNG written out byte by byte in the source.
What an outage looks like today
Today every image request goes through Cloudflare’s proxy straight to one server, which runs the image service beside Postgres, Redis and the rest of the product. The edge Worker described below is deployed but not routed, so it answers none of that traffic yet.
Most failures stay inside the rule, because the image service is still running and answering:
- A template that will not load, or an exception. The service card, and a real render on the next fetch once it is fixed.
- A spike past the service’s ceilings. The card, immediately, rather than a place in a queue. What breaks at five million sends has the ceilings.
- A lost signing key cache in Redis. Every image in that workspace becomes the card, because no signature can be checked. A sweep rewrites the keys from Postgres within five minutes.
- A worker process that dies. The service runs several, one fewer than the machine’s cores by default, and a dead one is replaced. A deploy drains requests in flight first.
- Postgres down. Nothing changes for recipients. The image service holds no database credentials and does not read Postgres on the render path.
The case outside the rule is the server itself being unreachable. Then nothing of ours is answering. Cloudflare can serve a copy its cache still holds, for as long as the headers allowed it to keep one: 30 seconds for a live countdown, a week for an expired timer or a static personalized image. Past that, Cloudflare answers with an error of its own, and a mail client draws an error as a broken image or as nothing. We would rather say that plainly than let the words “always 200” cover a case they do not.
What changes when the edge route is live
The Worker is written, tested and deployed on Cloudflare. It goes in front of the image service when its route is switched on, and from then on every open reaches it first.
Three things change for a recipient once it is.
Most opens stop reaching the server at all. The Worker keeps each render in Cloudflare’s cache under the exact signed query, so a repeat of the same image is answered at the edge.
An outage serves the last real image instead of an error. Every successful render is also kept as a last-known-good copy: a day by default, up to 30 days where the service allows it, as it does for static personalized images. When the service errors or takes more than ten seconds, the Worker serves that copy. A stale countdown is wrong by however long the outage lasts, and still better than a hole in the email.
Many expired timers stop depending on the server. Where the signed address carries its own deadline, as a per-recipient deadline or a send time does, the Worker can see that it has passed and rewrites every such request for the template to one canonical address. That one render is served from the edge cache for everybody, outage or not. A deadline set inside the template is not in the address, so those requests still go to the service.
With neither copy, the Worker answers with a transparent one-pixel PNG at HTTP 200, a different stand-in from the service card: the mail client sizes it from the width and height on your <img> tag and draws nothing, so the space holds. The same pixel answers a forged or unsigned address, which never reaches the server.
What a mail client’s own cache does with any of this
The service tells every cache how long it may keep each picture. The code asks private caches to keep a live countdown, the service card and a template fallback for zero seconds, so a recipient who opened during an incident gets a real render on the next open. An expired frame is the exception, at a day, because it will not change again.
What we measured on the live hostname is not quite that. Read on 24 September 2026 (UTC), the service card came back from img.emailtimer.app with max-age=14400, four hours, where the service sends zero. A Cloudflare zone setting, Browser Cache TTL, raises a lifetime the origin sets lower than its own. Until that setting is changed to respect the origin, a client that honours the header can show the card for up to four hours after the service has recovered. It is written here because it is true today.
Beyond the headers, each client keeps copies its own way, and nobody can purge them. Gmail fetches through Google’s image proxy, which publishes no cache lifetime (the Gmail page). Apple Mail with Mail Privacy Protection fetches at delivery rather than at open, so what Apple fetched during an outage is what a recipient may see later (the Apple Mail page). Outlook for Windows draws the first frame, and a stand-in is a still picture already.
What to put in the email so an outage costs less
Put the deadline in the body text as well as in the image, because text needs nothing from us. Set width and height on the <img> so any stand-in, including the edge pixel, keeps the layout. Write alt text that says the offer, such as “Sale ends Friday at midnight”, rather than “countdown timer”. Countdown timer not showing covers the reasons an image fails that have nothing to do with the service.
Nothing alerts us automatically yet: no uptime monitor, and no alert on the rate of service cards. An uptime check would stay green anyway, because every failure is a 200, which is why the service counts each card by its reason. The status page says what is watched and how an incident reaches you.
A security reviewer will ask the same question from the other side, and what a security review asks an email image service has the documents behind these answers. If you are weighing this against the vendor you use today, the matching question is what their addresses return once the contract ends, which moving off an incumbent without breaking mail already sent answers for each of them. The plan limits behind the countdown are on pricing.
Questions and answers
Does a recipient ever see a broken image icon?
Not from anything the image service sends. It can happen today in one case: the whole server is unreachable and Cloudflare holds no copy, so Cloudflare’s own error reaches the mail client. Once the edge Worker’s route is live, that case becomes the last real render or a transparent pixel.
Is a stand-in counted against our plan?
The service card is not counted. The expired frame and a template fallback are, because each is a rendered response for a real template. How opens are counted has the full rule.
Sources
Related
Put a countdown in the campaign you are writing now
The free plan covers 5,000 opens a month with no card. Starter is $19 a month for 250,000.