Skip to content

[Feature]: Migrate frontend CloudFront stack off StackSet pattern #2980

Description

@cqnykamp

Before submitting

  • I searched existing issues and did not find a duplicate request.

Affected area

Developer experience / tooling

Layer

Infrastructure / CI

Problem

The frontend CloudFront stack is deployed indirectly via a CloudFormation StackSet. The StackSet exists for one reason: ACM certificates attached to a CloudFront distribution must live in us-east-1, but the rest of the project's stacks deploy to us-east-2. To bridge the two regions, the frontend stack is wrapped in an outer StackSet that spawns a single StackInstance in us-east-1.

The indirection has real costs:

  • Anyone reading the deploy code has to understand CloudFormation StackSets before they can follow the frontend stack.
  • StackSet updates don't propagate template-only changes without a parameter delta, so the deploy script carries a ForceUpdateToken workaround that rewrites the params file on every run.
  • StackSet deploys are noticeably slower than direct stack updates (outer stack → instance update).
  • The StackSet's IAM administration/execution roles are shared by name across multiple stacks, creating hidden coupling that bites anyone trying to tear down or rename any one of them.
  • The us-east-1 region is hardcoded in several downstream places (bucket-name references in the GHA deploy role, region passed to the frontend GHA workflow), which propagates the indirection further out into the codebase.

None of this is blocking traffic — the system works. But every future change to the frontend distribution pays the StackSet tax.

Proposed solution

Replace the StackSet wrapper with two ordinary stacks deployed directly:

  1. A tiny cert stack in us-east-1 containing only the ACM certificate, publishing the cert ARN to SSM.
  2. The main frontend stack in us-east-2 (CloudFront, S3 buckets, OACs, CloudFront Functions, Route 53 alias, distribution-ID SSM parameter), consuming the cert ARN from the cert stack's SSM output.

To make this possible, aws-deploy.sh gains a per-stack region override (an associative array in the env config) so a single aws-deploy -s <env> run can target both regions. The deploy script's ForceUpdateToken workaround goes away. Bucket names move to us-east-2. The GHA deploy role and frontend workflow are updated to match the new region. The shared StackSet IAM roles are extracted into their own stack so other StackSet-shaped stacks aren't disrupted.

End state: one direct deploy per stack, one region override entry for the cert, no StackSet indirection, no force-update token, no shared-role coupling.

Alternatives considered

  • Do nothing. The system works today; the cost is cognitive, not operational. Reasonable choice if no one is iterating on the frontend distribution. The tax becomes worthwhile to pay down the next time a substantive change to the distribution lands (e.g. Migrate frontend and API to separate domains/distributions #2894 — splitting frontend and API onto separate distributions — would benefit from the simpler shape).

Additional context

Migration risks. Cutover involves a short downtime window (CloudFront + DNS propagation + CI bucket repopulate). Buckets get new names because the region is embedded in the name, so the rollover requires emptying the old buckets and republishing content. The shared StackSet IAM roles must be extracted first or other deploys break. The GHA deploy role's bucket allowlist needs a transitional state that grants both regions during cutover, or CI loses write access mid-migration. A safer cutover variant deploys the new stack in parallel under temporary bucket names and flips the apex DNS record once verified, preserving rollback.

Related. #2894 (split frontend and API distributions) touches the same template and would be cleaner against the simplified shape.

Metadata

Metadata

Assignees

No one assigned

    Fields

    Priority

    Low

    Effort

    Medium

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions