Skip to content

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 editor

What 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.json

To 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.json

Limits

LimitValue
Stored templates per AWS Region20,000
Stored template size (HTML and text)500 KB
Inline template input size1 MB
Replacement variables per templateNo limit
Destinations per SendBulkEmail call50

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.