Engineering5 June 2026

One template, every channel: how Notavia's rendering pipeline works

Scriban templates, per-channel rendering, idempotency keys, and a delivery log you can actually debug — the engineering behind Notavia's core loop.

The hardest part of building a multi-channel notification service is not the delivery. Connecting to an SMTP relay or a Vonage API is a solved problem. The hard part is the template — and specifically, keeping a single source of truth for your notification copy while producing output that is appropriate for each channel.

This post describes how Notavia solves that, and some of the engineering decisions behind idempotency and observability.

Scriban as the template engine

We chose Scriban for templates. It is a fast, logic-capable templating language with a clean syntax that reads well whether you are writing a full HTML email body or a 160-character SMS message.

A Notavia template lives in the console and has named slots per channel: email.subject, email.html, email.text, sms.body, in_app.title, in_app.body, and chat.text. When you trigger a send, Notavia determines which channels are active for the recipient, renders only those slots, and dispatches.

{{ recipient.first_name }}, your invoice for {{ data.amount }} is ready.

The same Scriban expression resolves in both the email subject and the SMS body. Channel-specific blocks let you include richer formatting — HTML, markdown-flavored in-app cards — without leaking it into channels that cannot render it.

Runtime editability and tenant overrides

Templates are deployed as part of your application configuration, but they are not locked to your deployment pipeline. Workspace administrators can edit template copy through the Notavia console and publish changes instantly — no code deployment required.

This matters for teams that serve multiple business customers. The default template is set by the product developer; individual tenants can override the copy for their branded communications. Notavia keeps a version history so you can roll back if a change produces unexpected output.

Idempotency keys

Every send request accepts an optional idempotency_key. If you supply one, Notavia will deduplicate: sending the same key twice within the deduplication window returns the original result without dispatching a second message.

This is not a nice-to-have. It is essential for any system that retries on failure. Without it, a transient network error between your application and the Notavia API can result in a duplicate notification — the invoice paid email sent twice, the security alert SMS appearing at midnight twice. With it, your retry logic becomes safe to run without defensive guards on your side.

The idempotency window is 24 hours by default and configurable per workspace.

Webhooks for every state change

Notavia emits a webhook for each state transition in the notification lifecycle: queued, dispatched, delivered, opened, clicked, bounced, failed. You subscribe to whichever events matter for your application.

The webhook payload includes the original send request, the resolved template output, the provider response, and the timestamp of each state change. Every webhook is signed with a shared secret so you can verify it arrived unmodified.

Webhooks are replayable from the console. If your endpoint was down during a delivery window, you can select the affected events and replay them without re-triggering the original send.

The delivery log

Every send produces a delivery record visible in the console. You can filter by template, by recipient, by channel, by status, and by time range. Each record links to the rendered output, the provider response, and the full webhook history.

The log is not just a debugging tool. It is the audit trail that answers questions from enterprise customers, GDPR regulators, and your own on-call engineer at 3am: "Did this message actually send? What did it say? When did it arrive?"

Building observability into the core delivery loop — rather than bolting it on later — is one of the core design principles of Notavia. Every call is traced. Every error is grouped and surfaced in the console. You should never have to grep your own application logs to understand what a notification sent two days ago actually contained.