Skip to content

Reuse bridge code for dev lambdas#6465

Open
MaTTaDox wants to merge 10 commits intoanomalyco:devfrom
MaTTaDox:reuse-live-bridge-code
Open

Reuse bridge code for dev lambdas#6465
MaTTaDox wants to merge 10 commits intoanomalyco:devfrom
MaTTaDox:reuse-live-bridge-code

Conversation

@MaTTaDox
Copy link

In dev mode, every aws.Function uploaded the same bridge zip as its own S3 object. This change deduplicates that upload so functions in the same region reuse one shared Live bridge asset.

Problem

Each Lambda in dev used identical bridge code (bootstrap from platform/dist/bridge) but still created/uploaded a per-function zip object.
This caused redundant uploads and long startup time of sst dev in bigger projects

Changes

  • Added an in-memory cache for Live bridge assets keyed by region:bundle.
  • In dev mode (non-container functions), create a deterministic bridge zip, hash it, and upload to:
    • assets/live-bridge-code-{hash}.zip
  • Reuse the same BucketObjectv2 promise for all matching functions.
  • Create the shared S3 object at stack root (pulumi.rootStackResource) with opts?.provider.
  • Use stable logical name: LiveBridgeCode{region}.

Validation

I currently use the version with this change locally and it works way facter than before.

Breaking Changes

With this release the s3 key of every lambda in dev mode gets replaced once and old objects getting deleted

@vimtor would be awesome if you can have a look at this. I am also open to alternative suggestions for this problem.
Thank you!

Add a lazy in-memory cache (liveBridgeCode) to avoid repeated creation/upload of live bridge code during dev. When dev=true, the code now builds a deterministic zip of the bundle (sorted files, zeroed timestamps, statConcurrency=1), hashes its contents, and uploads it as an s3.BucketObjectv2 using the region's bootstrap asset bucket. The Promise is cached by a region:bundle key and removed on failure to prevent duplicate work. Also thread the region value into the apply scope used for creating the zip and S3 object. This reduces repeated uploads and speeds up local development iterations.
Import pulumi and set the S3 BucketObjectv2 parent to pulumi.rootStackResource and pass opts?.provider. Also remove the component-specific name prefix from the BucketObjectv2 logical ID. These changes ensure the asset object is parented to the root stack resource and uses the correct provider, avoiding incorrect component scoping and provider resolution when creating the S3 object.
@vimtor vimtor self-assigned this Feb 24, 2026
@vimtor
Copy link
Collaborator

vimtor commented Feb 24, 2026

very cool @MaTTaDox

let me take a look once we merge the aws v7 upgrade

Replace usage of pulumi.rootStackResource and getRegionOutput(...).region with the imported rootStackResource and getRegionOutput(...).name. Also remove the namespace import of pulumi and import rootStackResource from @pulumi/pulumi. These changes standardize resource parent usage and access the region's name property where required in platform/src/components/aws/function.ts.
);
const partition = getPartitionOutput({}, opts).partition;
const region = getRegionOutput({}, opts).region;
const region = getRegionOutput({}, opts).name;
Copy link

@dsonet dsonet Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be .region? I see all other places are using .region now

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Youre right, thanks!

Comment on lines -2822 to +2900
region: getRegionOutput(undefined, { parent: this }).region,
region: getRegionOutput(undefined, { parent: this }).name,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this should be reverted too.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, it should be .region @MaTTaDox

@vimtor
Copy link
Collaborator

vimtor commented Mar 9, 2026

thanks for your contribution @MaTTaDox

haven't looked into this too much but from what i can remember i only seen logs like this when creating a new lambda function:

|  Created     Example sst:aws:Function → ExampleLogGroup aws:cloudwatch:LogGroup (1.1s)
|  Created     Example sst:aws:Function → ExampleRole aws:iam:Role (1.8s)
|  Created     Example sst:aws:Function → ExampleCode aws:s3:BucketObjectv2 (23.9s)
|  Created     Example sst:aws:Function → ExampleFunction aws:lambda:Function (7.4s)
|  Created     Example sst:aws:Function → ExampleInvokeFunction aws:lambda:Permission
|  Created     Example sst:aws:Function → ExampleUrl aws:lambda:FunctionUrl
|  Created     Example sst:aws:Function (36.7s)

in what cases does this pull request help then? when creating new functions? on live reload changes? initial startup times?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants