Data Model
EmailTemplate (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
locale VARCHAR NOT NULL DEFAULT 'en',
subject_template TEXT NOT NULL,
html_template TEXT NOT NULL,
text_template TEXT NOT NULL,
variables JSONB, -- schema: required fields + types
version INT NOT NULL DEFAULT 1,
active BOOLEAN DEFAULT TRUE
)
Template Rendering
Render subject line and both HTML and plain-text bodies by passing a context dict through Jinja2 or Handlebars. Always generate a plain-text alternative — many spam filters and corporate mail clients prefer or require it.
MJML
MJML is a responsive email framework: write semantic MJML markup, compile it to table-based HTML that renders consistently across Outlook, Gmail, Apple Mail, and mobile clients. MJML compilation runs server-side at template-save time; the compiled HTML is stored in html_template.
Multi-Language Support
Template lookup uses the composite key (name, locale). If no record exists for the requested locale, fall back to (name, 'en'). This allows partial localization: only translated templates need entries; untranslated templates automatically use the English default.
Variable Validation
The variables JSONB column stores a schema listing required fields and their types. Before rendering, validate that all required variables are present in the provided context. Return a 400 with the list of missing variables rather than rendering a broken email.
Preview API
POST /templates/:name/preview accepts a sample context body and returns fully rendered HTML for browser preview. Useful for template editors and QA. Preview does not send any email.
A/B Variant Testing
TemplateVariant (
template_id INT REFERENCES EmailTemplate(id),
variant CHAR(1) CHECK (variant IN ('a','b')),
html_template TEXT NOT NULL,
weight INT NOT NULL DEFAULT 50
)
At send time, select variant A or B via weighted random choice based on weight. Record which variant was sent per recipient to measure open and click rates. Winning variant can be promoted to the primary template.
Version History
Each edit creates a new row with an incremented version; the previous row is retained. Only the row with the highest version and active=TRUE is used for rendering. Rollback sets active=FALSE on the current version and active=TRUE on the target version.
Spam Score Check
On preview and before activating a new version, call the SpamAssassin API (or a hosted equivalent such as Mail-Tester) with the rendered HTML and text. Surface the score and flagged rules in the response. Reject activation if the score exceeds a configured threshold (e.g., 5.0) to protect sender reputation.
See also: Scale AI Interview Guide 2026: Data Infrastructure, RLHF Pipelines, and ML Engineering
See also: Atlassian Interview Guide
See also: Stripe Interview Guide 2026: Process, Bug Bash Round, and Payment Systems