Set up SPF, DKIM, and DMARC on AWS Route 53
Add SPF, DKIM, and DMARC as TXT records in your domain's Route 53 hosted zone using Create record — every value must be wrapped in double quotes, and DKIM keys over 255 characters must be split into multiple quoted strings separated by a space on one line.
Where to add records on AWS Route 53
AWS Management Console → search/open the Route 53 service → Hosted zones (left navigation pane) → click the name of your domain's hosted zone → records are managed on this page via the Create record button.
- Sign in to the AWS Management Console, open the Route 53 console, and choose Hosted zones in the left navigation pane.
- Click the name of the hosted zone for your domain (the zone whose name servers are authoritative for the domain you're configuring).
- Choose Create record. The console opens in whichever mode you last used: the simple Quick create record form, or the routing-policy wizard (a 'Choose routing policy' page). For a basic TXT record the Quick create form is easiest — if you land on the wizard instead, click 'Switch to quick create'. (If you'd rather use the wizard: keep Routing policy as 'Simple routing', choose Next, then 'Define simple record'.)
- In Record name, enter the host: leave it blank for the root/SPF record, enter _dmarc for DMARC, or enter the selector (e.g. selector1._domainkey) for DKIM. The zone's base domain is shown as a greyed-out suffix beside the field — don't retype it.
- Set Record type to TXT.
- In Value, paste the full record wrapped in double quotes, e.g. "v=spf1 include:_spf.google.com ~all". Set TTL to 300–3600 seconds and leave the routing policy as Simple.
- Choose Create records. Route 53's own name servers update quickly — the change reaches INSYNC (the propagation status returned by the GetChange API) generally within ~60 seconds.
The three records on AWS Route 53
SPF Sender Policy Framework
Leave the Record name field blank to create the SPF record at the root domain (Route 53 defaults the name to the zone apex automatically — do NOT type @, which AWS explicitly warns against and which would create a literal '@' subdomain). Record type TXT, value like \"v=spf1 include:_spf.google.com ~all\" in double quotes. Publish only ONE SPF string at the root. Route 53 won't let you create a second TXT record SET with the same apex name and type, so if a root TXT record set already exists (e.g. a domain-verification string), add the SPF string as an additional value on a new line inside that SAME record set.
DKIM DomainKeys Identified Mail
Route 53 does not generate DKIM keys — get the exact host/name and value from your email provider (or from Amazon SES if you send through SES). Enter the provider's selector in Record name (e.g. selector1._domainkey or, for SES, the token like xxxx._domainkey). Provider DKIM is usually a TXT record; Amazon SES Easy DKIM instead gives you three CNAME records (use record type CNAME for those, with no quotes). For a TXT DKIM key longer than 255 characters (typical for 2048-bit keys), Route 53 rejects it with the error CharacterStringTooLong — split the value into ≤255-char chunks, wrap EACH chunk in double quotes, and separate them with a single space, all on the SAME line: \"v=DKIM1; k=rsa; p=FIRST_CHUNK\" \"SECOND_CHUNK\". Resolvers concatenate the quoted strings back together with no spaces added.
DMARC reporting and policy
Create a separate TXT record with Record name set to exactly _dmarc (Route 53 appends your zone's domain, producing _dmarc.yourdomain.com — don't type the full _dmarc.yourdomain.com or it doubles the domain). Value in double quotes, e.g. \"v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com\". Start at p=none to monitor, then tighten to quarantine/reject once your SPF and DKIM are passing.
Need the record values? Generate a valid SPF and DMARC record with the record generator, then learn what each one does: SPF, DKIM, DMARC.
AWS Route 53 gotchas
- Double quotes are mandatory and NOT auto-added — Route 53's TXT Value box requires you to type the surrounding double quotes yourself; an unquoted value is rejected as a formatting/validation error (InvalidChangeBatch). The console does not silently wrap or strip them the way some hosts do.
- Newlines in the Value box mean SEPARATE TXT values, not continuation. The console treats each line as a distinct value in the record set (for TXT/most types you can enter multiple values, one per line) — correct for holding two different TXT records together (e.g. SPF + a verification token), but WRONG for one long DKIM key, which must stay on a single line as space-separated quoted chunks or DKIM validation breaks.
- Use blank for the root and the bare host for subrecords — Route 53 always appends the zone apex to whatever you type in Record name. AWS specifically warns not to enter @ (it creates a literal @ host), and entering _dmarc.yourdomain.com produces _dmarc.yourdomain.com.yourdomain.com.
- Propagation across Route 53's own name servers is fast — the change reaches INSYNC (the status returned by the GetChange API; the records list itself doesn't show a per-record INSYNC badge) generally within ~60 seconds. But global resolver caching still honors the TTL you set, so use a low TTL (300s) while testing and confirm with dig/nslookup before relying on the change.
- Route 53 only serves the domain if the registrar's name servers point to THIS hosted zone's four NS records. Editing records in a hosted zone that isn't the authoritative one (a common duplicate-zone mistake — e.g. a second zone auto-created for the same domain) changes nothing live.
Records set. Now make sure you actually land.
SPF, DKIM, and DMARC on AWS Route 53 get you authenticated, but inbox placement also needs sender reputation and domain warmup. Scheduler Zero handles both so your cold email reaches the inbox.