Guide
Amazon SES email templates: a practical guide.
Last updated 30 September 2026
Everything you need to create, send, and maintain stored email templates in Amazon SES, from the JSON structure to Handlebars features and the limits worth knowing.
Skip the JSON
Design SES templates visually, keep Handlebars logic intact, and publish straight to Amazon SES.
Open the editorWhat an SES template is
An Amazon SES stored template is a named resource in your SES account holding a subject, an HTML body, and a text body, each with placeholders. When you send, you pass the template name and a JSON object of values, and SES renders a personalised message for each recipient.
SES also supports inline templates, where the content travels in the send call instead of being stored. Stored templates are easier to reuse and update without redeploying code, which is why most teams use them for receipts, password resets, and onboarding email.
Template structure
In the SES v2 API, a template has a name and TemplateContent with three parts:
{
"TemplateName": "order-receipt",
"TemplateContent": {
"Subject": "Your receipt, {{firstName}}",
"Html": "<h1>Thanks, {{firstName}}</h1>{{#each items}}<p>{{name}}: {{price}}</p>{{/each}}",
"Text": "Thanks, {{firstName}}\n{{#each items}}{{name}}: {{price}}\n{{/each}}"
}
}Keep Text in sync with Html: recipients whose clients don’t display HTML see the text part. When writing JSON by hand, the HTML must be a single escaped string with no raw line breaks.
Handlebars in SES
SES renders stored templates with Handlebars and supports nested attributes, array iteration, basic conditionals, and inline partials (AWS documentation):
{{! Nested attributes }}
Hello {{contact.firstName}}
{{! Loops }}
{{#each items}}
<li>{{name}}: {{price}}</li>
{{/each}}
{{! Conditions }}
{{#if isTrial}}
<p>Your trial ends on {{trialEndsOn}}.</p>
{{else}}
<p>Thanks for being a customer.</p>
{{/if}}Inline partials are defined per part, so a partial used in both HTML and text must be defined in both.
Create a template
Save the structure above as order-receipt.json and run:
aws sesv2 create-email-template --cli-input-json file://order-receipt.jsonTo change it later, use update-email-template with the same shape. list-email-templates and get-email-template show what’s deployed.
Send with a template
Call SendEmail for one destination or SendBulkEmail for up to 50 destinations per call, passing TemplateData as an escaped JSON string:
{
"FromEmailAddress": "Northwind <billing@northwind.example>",
"Destination": { "ToAddresses": ["ada@example.com"] },
"Content": {
"Template": {
"TemplateName": "order-receipt",
"TemplateData": "{ \"firstName\": \"Ada\", \"items\": [{ \"name\": \"Team plan\", \"price\": \"$120.00\" }] }"
}
},
"ConfigurationSetName": "transactional"
}aws sesv2 send-email --cli-input-json file://send.jsonLimits
| Limit | Value |
|---|---|
| Stored templates per AWS Region | 20,000 |
| Stored template size (HTML and text) | 500 KB |
| Inline template input size | 1 MB |
| Replacement variables per template | No limit |
Destinations per SendBulkEmail call | 50 |
Source: Using templates to send personalized email (AWS documentation).
Common pitfalls
- Silent rendering failures. SES can accept a message whose data doesn’t render and then not deliver it. Publish Rendering Failure events to SNS through a configuration set.
- Unescaped input. SES doesn’t HTML-escape values in the HTML part. Escape user-entered data before putting it in
TemplateData. - Drift. When templates are edited in several places (console, scripts, a teammate’s CLI), the deployed version stops matching what anyone has locally. Pick one source of truth.
- Previewing blind. Hand-written JSON gives no sense of how the email looks with real data in real inboxes. Test with realistic data, including empty lists and missing values.
Editing without JSON
Huskar Send is a visual editor built for SES templates. You design with blocks, conditions and loops stay real Handlebars, and merge tags are chips with {{ autocomplete. Preview uses sample data profiles in Gmail, Apple Mail, and Outlook frames. When you’re ready, publish creates or updates the template in your SES account through an IAM role you control, and it warns you before overwriting a template that was edited directly in SES.
You can try it in your browser without an account, and export SES template JSON at any time. Moving off Amazon Pinpoint? See the Pinpoint to SES template migration guide.
FAQ
Does Amazon SES have a visual template editor?
No. SES stores templates and renders them when you send, but the console and API work with raw HTML, text, and JSON. Visual editing needs a separate tool such as Huskar Send, which designs templates visually and publishes them to your SES account.
What template language does Amazon SES use?
SES stored templates use Handlebars. You can use placeholders, nested attribute paths, each loops, if and else conditions, and inline partials.
How many templates can I store in Amazon SES?
Up to 20,000 stored email templates in each AWS Region. Each template can be up to 500 KB including both the HTML and text parts. Inline templates, sent with the content in the API call, can be up to 1 MB and do not count against the 20,000 limit.
What happens if template data is missing or invalid?
SES might accept the message but fail to deliver it. AWS recommends a configuration set that publishes Rendering Failure events to Amazon SNS so you can see which message failed and why.
Can I preview an SES template before sending?
SES has a TestRenderEmailTemplate operation that returns the rendered message for given data. Huskar Send adds visual previews in Gmail, Apple Mail, and Outlook frames with sample data profiles, before you publish.