fix(aws/function): do not fetch the IAM role eagerly when role is passed - #6942
Open
peter-boompop wants to merge 1 commit into
Open
fix(aws/function): do not fetch the IAM role eagerly when role is passed#6942peter-boompop wants to merge 1 commit into
role is passed#6942peter-boompop wants to merge 1 commit into
Conversation
…ssed When `role` is set, the Lambda is wired up from that ARN directly, so the `iam.Role.get()` result only ever backs the `nodes.role` getter. That lookup is a Pulumi `read`, which is never treated as unchanged, so it costs an IAM GetRole on every run — once per function. Apps that share a single role across many functions therefore pay N reads for one role. That pattern is the practical way to stay under the IAM roles-per- account quota at scale. On a 3,576-resource app with 440 functions sharing one role, a no-op `sst dev` spent 367s in `pulumi up`; deferring the lookup brings it to 29s. Make the lookup lazy so it only runs if `nodes.role` is read. The default path (no `role` passed) still creates the role eagerly — it is consumed inside an `apply` in createFunction and must not be deferred. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
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.
Title: fix(aws/function): don't fetch the IAM role eagerly when
roleis passedThe problem
When
roleis passed tosst.aws.Function,createRole()immediately does:That's a Pulumi
readop. Reads are never treated as unchanged — by design, a read exists to fetchcurrent truth — so it hits
iam:GetRoleon everysst dev/sst deploy, once per function.But the fetched Role is never used for anything functional. The Lambda is wired up from the ARN that
was already passed in:
Its only consumer is the
nodes.rolegetter. So each call is an IAM round-trip to populate a getterthat most apps never read.
This gets expensive for apps that share one role across many functions — which isn't exotic. It's
the only practical way to stay under the IAM "Roles per account" quota at scale: N functions × M
stages roles adds up fast, and one shared role collapses that to M. Doing the quota-friendly thing
currently costs N IAM reads per run.
Impact (measured)
On a real app: 3,576 resources, 440
sst.aws.Functions sharing a single execution role, 38 stages.A true no-op
sst dev(zero creates, zero updates):pulumi upwall timereadops onaws:iam/role:Rolesamesame~12.6×. The state pushes collapse as a side effect — each read resolving was forcing a checkpoint of
a 25MB state file.
The fix
Return a memoized thunk from
createRole()so the.get()only runs ifnodes.roleis actuallyread. Uses the existing
lazy()helper, already imported in this file.Behaviour is unchanged:
nodes.rolereturns the same Role as before, just fetched on demand.args.rolealready took precedence).rolepassed — still creates the role eagerly. That matters:roleisconsumed inside an
applyincreateFunction, so deferring the create path would register aresource inside an apply. Only the
.get()is deferred.Verification
bun run typecheck:platformpasses.platformvitest: 100 passed. 3 test files fail withERR_TRACE_EVENTS_UNAVAILABLEon mymachine, but they fail identically on unmodified
dev— pre-existing/environmental, unrelated.same. On the first run after the change, Pulumi emits a one-timediscardwave retiring the nowunused read-entries from state.
discardis state-only — Pulumi never deletes resources it merelyread — so no IAM role is touched. It doesn't recur.
Note on scope
The same pattern exists in a few other components —
fargate.ts(taskRole,executionRole),vpc.ts,cognito-identity-pool.ts. I've kept this PR toFunctionsince that's where I havemeasurements, but happy to extend it if you'd like.