Build vs. buy
“We’ll just self-host Satori.” Sure — here’s what that actually means.
Satori is genuinely great, and for a single static image size it’s a weekend project. We’re not going to pretend otherwise. But “free on Cloudflare Workers” quietly assumes your needs never grow past a basic PNG. Here’s the fuller picture, from a team that hit every one of these.
The “free on Workers” catch
Cloudflare Workers can’t run Chromium. So a Workers-hosted Satori server maxes out at Tailwind → PNG. No PDF. No charts, no diagrams, no math. The instant a customer asks for a downloadable PDF invoice, the “free” architecture has to be rebuilt on a platform that can run a real browser — which is a very different cost and ops story.
Satori renders images, not PDFs
Satori turns HTML into an SVG you rasterize to PNG. It has no concept of paged media — no PDF, no page breaks, no A4/Letter. The moment you need an invoice as a PDF you're standing up a whole second runtime: headless Chromium.
Charts, diagrams, and math need a real browser
Chart.js, Mermaid, and KaTeX all rely on real browser layout that Satori can't do. Supporting them means driving Chromium, capturing screenshots at the right device-scale, and embedding the result — each with its own sizing pitfalls.
Satori speaks a Tailwind dialect, not Tailwind
Its built-in Tailwind support has no gap-* utility at all, caps color palettes at shade-900 (no -950), and ignores arbitrary values. You end up rewriting existing components with margins instead of gaps just to get them to render — and debugging cryptic "expected display:flex" errors when you forget.
Fonts are their own project
Satori needs ttf/otf/woff — woff2 is unsupported, so you can't just point at Google Fonts' modern files. It also trims whitespace at text-node boundaries, so tokenized code and Markdown lists come out mangled until you anchor spaces with zero-width characters.
A warm Chromium pool that doesn't fall over
Cold-starting Chromium per request is slow; keeping one warm means managing a long-lived browser process, recycling pages, bounding concurrency, and shipping the right binary for your host. That's infrastructure you now operate 24/7.
Everything that isn't rendering
Per-key authentication, credit metering, rate limiting, idempotency so retries don't double-bill, saved templates, batch endpoints, usage logs. None of it is "rendering," all of it is required before real customers can depend on your service.
When you should self-host
If you need one image size, from simple markup, at low volume, and you enjoy owning the maintenance — genuinely, self-host. You’ll learn a lot and it’ll work.
Renderfy exists for the day after that: when you also need PDFs, charts, brand fonts, deterministic output, retries that don’t double-bill, and batch — and you’d rather ship your product than operate a rendering platform. One API call, a fraction of a cent, none of the infrastructure. We already paid for the three weeks of gotchas above so you don’t have to.