How MakiSend runs on Cloudflare
One Worker, one database, one queue and a durable workflow. Nothing to keep running, all of it on your own Cloudflare account.
Follow one email
Pick what happens at your SMTP provider, then send. Each stop is a Cloudflare product.
- Your appPOST /send-email
- WorkerWorkers
- DatabaseD1
- QueueQueues
- WorkflowWorkflows
- Your SMTPTCP sockets
- InboxDelivered
- Dead lettersQueues (DLQ)
Press Send to follow one email.
The Cloudflare products behind it
Workers (Cloudflare docs, opens in a new tab)
One Worker runs everything: the Hono API, sign-in, the dashboard and the delivery code.
nodejs_compat lets nodemailer and its SMTP client run unchanged. No server, no container.
Static Assets (Cloudflare docs, opens in a new tab)
Serves the dashboard (an Astro build) from the same Worker, on the same origin as the API.
Same origin means no CORS and one URL to remember.
D1 (Cloudflare docs, opens in a new tab)
The database: email logs and history, encrypted contents and attachments, SMTP configurations, API keys, templates, accounts.
Recipients, bodies, attachments and SMTP credentials are AES-256-GCM encrypted before they are written. Schema managed by Drizzle migrations.
Queues (Cloudflare docs, opens in a new tab)
Decouples the API from delivery: the request ends as soon as the email id is queued.
Batches of up to 10, 3 consumer retries 30 seconds apart, then a dead-letter queue (makisend-send-email-dlq).
Workflows (Cloudflare docs, opens in a new tab)
One durable run per email. Its id is the email id, so the same email can never be sent twice by two runs.
4 SMTP attempts, 30 seconds apart, that survive restarts. Permanent errors (auth, TLS, DNS, 5xx) stop at once. Every step is written to the email's history.
TCP sockets (Cloudflare docs, opens in a new tab)
The Worker opens the SMTP connection to your provider itself, over TLS.
Ports 465, 587, 2465, 2525 and 2587. Port 25 is blocked by Cloudflare. Connections leave from shared Cloudflare IPs.
Email Service (Cloudflare docs, opens in a new tab)
An alternative to SMTP: configurations on smtp.mx.cloudflare.net send through the Worker's send_email binding.
No SMTP password needed; the sender address must use a domain onboarded to Cloudflare Email Sending.
Cron Triggers (Cloudflare docs, opens in a new tab)
Background jobs with no extra service: health checks, the update check and key rotation.
Daily at 03:17 UTC and hourly at minute 17 (see below).
Workers Logs (Cloudflare docs, opens in a new tab)
Request and invocation logs from the Worker, in your Cloudflare dashboard.
Turned on in wrangler.jsonc. Email contents are never logged.
What runs on a schedule
- Every day, 03:17 UTC
- Tests every SMTP configuration and records the result, then checks GitHub for a new MakiSend release (unless UPDATE_CHECK is off).
- Every hour, minute 17
- Key rotation: re-encrypts stored data still under a previous ENCRYPTION_KEY, in small batches.
What to know before you rely on it
- No fixed outbound IP: a provider that requires IP allow-listing will refuse sends from a Worker.
- Sending is asynchronous: the 202 means queued, not delivered. The outcome is in the logs and the dashboard.
- One SMTP provider per configuration, no automatic failover. No bounce, open or click tracking yet.
- Deliverability depends on your sender domain (SPF, DKIM, DMARC) and your provider, not on Cloudflare.
The full design, data model and diagrams are in the README and docs/ARCHITECTURE.md.