Repository navigation
Conversation
A Function with versioning: { alias: "live" } creates a Lambda alias on the
version it publishes, and creates its function URL on that alias. Router
routes, and SsrSite servers through transform.server, then serve whatever
version the alias points to, so a rollback is an alias move.
- transform.alias, e.g. to ignore functionVersion when a tool outside SST
moves the alias
- URL permissions, including CloudFront OAC grants in Function and SsrSite,
are granted on the alias
- the SsrSite warmer warms the alias, and links can invoke it
- not supported together with durable, which has an alias of its own
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A Function with
versioning: { alias: "live" }creates a Lambda alias on the version each deploy publishes, and creates its function URL on that alias. Router routes andSsrSiteservers use that URL, so they serve whichever version the alias points to, and a rollback is just moving the alias.Problem
Lambda aliases are the standard way to roll back without a deploy: publish a version on every deploy, send traffic to an alias, and point the alias at an earlier version when something breaks (
aws lambda update-alias --name live --function-version 41). It takes effect at once, and nothing gets rebuilt.SST always creates function URLs on
$LATEST, so the alias never gets traffic. For a site behind a Router it's worse:SsrSitebuilds the Router metadata from the server's URL,and there's no option or transform that changes which URL that is.
transform.servercan turn onversioning, but it can't move the URL, and theKvKeysresource that writes the metadata isn't exposed.SST already does this for durable functions, whose URL is created on an alias in
createUrl. It's just not available for anything else.Use case
We run several Next.js sites with
sst.aws.Nextjsbehind one Router, and want to roll back a bad deploy from a console in seconds, without runningsst deployon an old commit while the site is broken. To get an alias into the traffic path today we:servershost in SST'sKvKeysinputs with a Pulumi stack transformation, matched by SST's internal resource name;$LATESTbefore its alias URL is deleted when it leaves the rollout. Without that, CloudFront signs requests for a URL that no longer exists and the site answers 403 until SST happens to rewrite the metadata;warminvokes$LATEST.All of it depends on SST internals: the
KvKeysresource name, the shape of the metadata, and there being exactly oneserversrow. With this PR, all of it goes away. ForNextjsit's atransform.server:Design
Functionversioningalso takes{ alias }. It creates alambda.Aliaswith that name, pointing at the published version, and turns onpublish.urlis enabled, the function URL is created on the alias (qualifier). Router routes andSsrSitemetadata use that URL, so they follow it with no other changes.transform.aliaschanges the alias resource. A tool that moves the alias outside of SST can stop deploys from moving it back withignoreChanges: ["functionVersion"]. Without that, a deploy moves the alias to the version it published. A deploy with no code changes publishes no new version, so it leaves a rolled-back alias alone.nodes.aliasexposes the alias, and links include its ARN so linked resources can invoke it.durableit throws aVisibleError, since durable functions already put their URL on an alias of their own.SsrSitewarmcron invokes<name>:<alias>, since that's what the URL serves.component.tsaws:lambda/alias:Aliasis added to the resources whose physical names aren't prefixed. Alias names are scoped to their function, likeFunctionUrlandPermission, which are already on that list.Unchanged without an alias. Every resource gets the same inputs as before.
qualifierresolves toundefinedand isn't sent.Adding or removing the alias replaces the function URL, so its hostname changes. This is documented on the option. The Router metadata is updated to the new URL in the same deploy, and Pulumi deletes replaced resources at the end of a deploy, so the old URL should outlive the switch.
Open questions
versioning.aliaskeeps it next topublish.url.aliaswould say more clearly what changes, but an alias is useful without a URL too.versioning: true,targetArn(API Gateway routes, subscribers, …) is the published version. Should those use the alias when there is one, so a rollback covers every trigger? That's a bigger change, so I left it out.SsrSiteoption.server.versioningonSsrSitewould be nicer thantransform.server. Happy to add it.Relation to #7030 and #7034
Independent of both. #7030 minifies the Router's viewer-request function, and #7034 lets an injection pick the server host for one request. This changes which host a site's metadata names for everyone.
Testing
test/components/function-alias.test.ts, 8 tests. It builds realFunctions and aRouterunder Pulumi mocks, with only theRuntime.BuildRPC, the bootstrap bucket lookup and the dynamic KV providers stubbed. It checks that:urlreturns the alias URL;transform.aliascan change the alias and setignoreChanges;tsc --noEmitpasses, and all 108 platform tests pass.Run with
vitest run --pool=forks: on Node 22 the default threads pool reportsERR_TRACE_EVENTS_UNAVAILABLEfrom Pulumi's closure serialization, the same asrouter-waf.test.tsondev.bucket,albandservice-albfail to load in my install ondevas well (@types/noderesolve), so they're unrelated.