Authenticating...
Skip to main content

Amplify Domain Recreation

When to use this

Use this when an AWS Amplify custom domain (e.g. adunits.adgem.com, offerwall-ui) is stuck — the TLS cert won't issue or renew, or Amplify shows the domain misconfigured — and the fix is to delete and recreate the domain from scratch.

This came out of IR-275 (SEV-1, 2026-05-08): the Amplify-managed cert for adunits.adgem.com expired without auto-renewing, and recreating the domain took ~2 hours longer than it should have because of the DNS-ordering gotcha below.

Remove the stale application CNAME first

The #1 mistake that extends every one of these incidents: re-adding the subdomain's DNS CNAME before removing the stale one from the previous attempt. Amplify's verification will silently fail against the old value and you'll be stuck watching Verifying domain... indefinitely. (The ACM validation record is the exception — see step 2; it may need to stay.)

Prerequisites

  • AWS console access to the app's Amplify-hosting account (for adunits.adgem.com / offerwall-ui, that's offerwall-ui-prod, account 992382388063)
  • Cloudflare access to the adgem.com zone (DNS is managed there, not in Route 53)

Steps

  1. In Amplify → Domain management, delete the existing custom domain association for the affected domain.

  2. In Cloudflare, search the DNS records for the subdomain (e.g. adunits). You will find two CNAME records tied to it, and they are not treated the same:

    1. The subdomain record itself (e.g. adunits.adgem.com → some *.cloudfront.net) — always delete this one. It points at the distribution you just detached and is the stale value that silently fails verification.

    2. The ACM validation record — a random-looking prefix (e.g. _a1b2c3....adunits.adgem.com). Check for dependencies before deleting it. ACM issues one validation record per FQDN per account and reuses it for renewals and for replacement certificates, so deleting it stops auto-renewal for any still-active certificate covering this domain. List them first and leave the record in place if any are in use:

      aws acm list-certificates --region us-east-1 --profile offerwall-ui-prod \
      --query "CertificateSummaryList[?DomainName=='adunits.adgem.com'].[CertificateArn,Status,InUse]" \
      --output table

      Delete it only when no active certificate depends on it. A correct validation record left in place is harmless and helps — the replacement certificate can validate against it immediately.

  3. Confirm the CloudFront alias is free, then re-add the custom domain in Amplify, pointing it at the correct branch. CloudFront refuses an alternate domain name that is already associated with another distribution — including a distribution in an AWS account you can't see — and reports this as CNAMEAlreadyExistsException. If step 1's deletion didn't fully release the alias, or a distribution in another account still claims it, the re-add fails until it's resolved:

    • Check this account first:

      aws cloudfront list-distributions --profile offerwall-ui-prod \
      --query "DistributionList.Items[?Aliases.Items && contains(Aliases.Items, 'adunits.adgem.com')].[Id,DomainName,Status]" \
      --output table

      (The Aliases.Items && guard matters — without it the query errors out on any distribution that has no alternate domain names.) If a distribution here holds the alias, remove it from that distribution.

    • For a cross-account holder, aws cloudfront list-conflicting-aliases / list-domain-conflicts returns the owning account ID partially masked — enough to tell whether it's ours. Then follow AWS's move an alternate domain name procedure.

    • If the association is in an account nobody can access, or is orphaned from a deleted resource, open an AWS Support case — it cannot be cleared from our side and every re-add attempt will keep failing until AWS releases it.

    Also confirm you're not accidentally configuring a sibling domain — IR-275 briefly mixed up adunits config with a similarly-named domain.

  4. Amplify will issue a new ACM certificate and a new CloudFront distribution. Open Actions → View DNS records (sometimes just labeled "DNS entries") to get the fresh CNAME values. Do not reuse the subdomain value from a previous attempt — the CloudFront hostname changes on every recreate. The ACM validation pair is usually identical to the one from before (ACM reuses it per FQDN per account), which is expected, not a sign you copied a stale value.

  5. Add the new CNAME values to Cloudflare: one for the subdomain, one for the ACM validator. The ACM validation record must be proxy status DNS-only (grey cloud) with Flatten disabled. A proxied record answers with Cloudflare's own IPs instead of the _....acm-validations.aws target, and flattening rewrites the CNAME into A records — either one makes ACM validation fail. If the zone has "Flatten all CNAMEs" enabled (DNS → Records → Settings), disable it, or scope flattening so it doesn't cover this record. This record must stay DNS-only after verification — ACM re-checks it on every renewal, not just at issuance.

  6. Wait for DNS propagation and ACM validation. Amplify often flips to verified within about 30 minutes, but ACM allows far longer: a pending request is only marked Validation timed out after 72 hours. Slow propagation is normal and is not by itself evidence of a stale record. Verify both records resolve to the step 4 values before concluding anything is wrong:

    dig +short adunits.adgem.com CNAME
    dig +short _<validation-prefix>.adunits.adgem.com CNAME

    The first must return the new *.cloudfront.net hostname; the second must return the _....acm-validations.aws value from step 4. An old value, an empty answer, or A records instead of a CNAME points at a specific fix — stale record (step 2), proxy enabled, or CNAME flattening (step 5).

    Escalation threshold: once both dig checks return the expected values, give it up to 2 hours. If Amplify still isn't verified, do not recreate the domain again — each recreate issues another certificate and distribution and restarts the 72-hour ACM window. Instead check the certificate's validation state directly and escalate to Platform / AWS Support:

    aws acm describe-certificate --region us-east-1 --profile offerwall-ui-prod \
    --certificate-arn <arn> \
    --query 'Certificate.DomainValidationOptions[].[DomainName,ValidationStatus,ResourceRecord.Name,ResourceRecord.Value]' \
    --output table
  7. Once Amplify shows the domain as verified/active, confirm the site loads over HTTPS with a valid cert, then unmute any monitors that were muted during the incident.

Why this is finicky

  • Amplify hides the underlying CloudFront distribution — deleting and recreating the domain creates a new distribution with a new hostname, so any previously-noted CloudFront hostnames are invalidated.
  • The custom domain config for this app is currently clickops, not IaC (PLA-188 tracks migrating it) — so there's no diff or history to check when something looks wrong, only what's live in the console.
  • Cloudflare is the DNS authority here, not Route 53. If you're used to ACM + Route 53 auto-validation, this manual CNAME shuffle is the gap that trips people up.
  • IR-275 incident / postmortem
  • PLA-186 — investigate why the cert didn't auto-renew in the first place
  • PLA-187 — route Amplify/ACM expiry alerts to Slack (would catch this before it becomes an incident)
  • PLA-188 — move this config to IaC so this whole runbook becomes unnecessary