Migrating from Serverless Framework v3 to Pulumi —...
# general
c
Migrating from Serverless Framework v3 to Pulumi — Best practices for large-scale Lambda projects? Hi everyone! I'm a backend developer relatively new to infrastructure management. I'd appreciate any guidance on my migration journey. Background: We're running Serverless Framework v3, which is hitting Node.js version compatibility issues. While evaluating alternatives, we found Pulumi and decided to give it a try. Our setup: - ~100 Lambda functions - Heavily interconnected AWS resources: SQS, SNS, SES, EventBridge, DynamoDB, API Gateway, VPC, etc. What we tried: We used Claude Code (AI coding assistant) to convert our serverless.yml definitions into Pulumi code and deployed to our dev environment — but ran into errors. Root cause: Serverless Framework implicitly creates a significant number of resources behind the scenes (IAM roles/policies, CloudWatch Log Groups, Lambda permissions, API Gateway integrations, SQS/SNS subscriptions, DLQ configurations, etc.) that aren't explicitly defined in serverless.yml. Claude Code had no way to know about these implicit resources, so they were missing from the generated Pulumi code. This led to deployment failures and highlighted a reliability concern — relying on AI to fully capture infrastructure definitions it can't fully "see." The challenge: With ~100 Lambdas and dozens of interconnected event sources, manually auditing and defining every implicit resource that Serverless Framework auto-generates feels impractical. What I'm looking for: - Are there any best practices or established migration paths from Serverless Framework to Pulumi for projects of this scale? - Does anyone know of a tool or approach that can introspect the actual deployed CloudFormation stack and generate corresponding Pulumi code (e.g., pulumi import, cf2pulumi, or similar)? - Has anyone successfully migrated a large Serverless Framework project and can share their strategy for handling the implicit resource gap? Any advice, tooling recommendations, or lessons learned would be greatly appreciated. Thanks!
l
Presumably, most of your roles, policies etc. are identical and should be rationalised and shared. In this case, I find it's best to have a project which sets up all the re-usable resources (and exports the important IDs), and one project per tightly-cohesive set of lambdas, which imports and uses those shared IDs. The up-front work isn't trivial but it's not too hard, and the overall result is often a significant reduction in deploy resource count and corresponding improvement in IaC maintainability.
You cannot get AI-generated code to see everything. Just assume it's going to miss stuff. Even the trivial webapp-in-an-S3-bucket demo app I'm using right now can't be built using Neo: it misses the contents of the S3 bucket (the BucketObjects). And it builds a really awful policy document that's really easy to improve by hand. These are the sorts of things you have to live with when you attempt to vibecode.
c
Thanks for the insights! I completely agree that AI-generated infra code will always miss things — that's exactly what we experienced. I've since discovered that Serverless Framework uploads a compiled-cloudformation-template.json to S3 on every deploy. This is the fully resolved CloudFormation template that includes all the implicit resources — IAM roles/policies, CloudWatch Log Groups, Lambda Permissions, Lambda Versions, Event Source Mappings, SQS Queue Policies, API Gateway integrations/routes, etc. For example, our core-service alone compiles to a template with ~60 resources including: - 7 Lambda functions + 7 Lambda Versions - 7 CloudWatch Log Groups - 1 shared IAM Role with inline policies + VPC execution managed policy - 6 EventBridge Rules + 6 Lambda Permissions for schedules - 3 SQS Queues + 3 DLQs + Queue Policies - 3 Lambda Event Source Mappings (SQS triggers) - 2 SNS Subscriptions + SNS Lambda Permission - API Gateway integrations + routes - S3 deployment bucket + bucket policy None of these (except the Lambdas and SQS queues) were explicitly defined in our serverless.yml — they were all auto-generated. My question: Has anyone used a workflow like this for migration? 1. Take the compiled-cloudformation-template.json from S3 2. Feed it into cf2pulumi or pulumi import to generate Pulumi code 3. Refine and rationalize the output (e.g., consolidating shared IAM roles as you suggested) Would cf2pulumi handle a template like this reliably? Or is pulumi import (importing from the live stack) a better approach? Any gotchas or recommendations from anyone who's tried this path? We have ~10 services, each producing a similar compiled template, so if this workflow is viable it could significantly reduce the manual effort of identifying all implicit resources.
l
Neo will handle it nicely, if you're paying for the right Pulumi license. Its cloud-specific smarts are impressive. However, it greatly benefits from good Pulumi domain knowledge, so you know what reworkings you ought to request. No idea about cf2pulumi, sorry.
pulumi import
with a bulk import would be good, though it will require some massaging of the input JSON first. Any old LLM client should handle that, with a reference input and output format to work with. Pulumi Insights will generate the equivalent code as
pulumi import
, and without the upfront massaging, but it requires the same license as Neo. And imo, plain Neo is better, it tends to produce more idiomatic code.
The main gotchas I have found are that in AWS (non-native/cloud control), the cloud resources don't always match the Pulumi resources, so you can't rely on resource count as a measure of success. E.g. a single AWS bucket may take 4 or 5 Pulumi resources to fully describe.
And idiomaticness is impossible. You need a real programmer to fix policy docs, file assets, and things like that. Even the example code in Pulumi's repos often do things in what I consider to be the "wrong" way. tmtowtdi, apparently.
s
The problem with cf2pulumi is that it translates to AWS CloudControl instead of the AWS resources (they're different providers, and you should always prefer the AWS provider), so I would recommend not using cf2pulumi.
Given that Serverless Framework always produces a CloudFormation stack, you're going to want to use that output to drive whatever conversion method you choose. I would definitely favor an LLM to do the conversion, either Neo or your favorite local LLM.
☝️ 1
c
I have translated dozens of serverless projects to Pulumi and SAM -not with AI though. Everything is straight-forward except for API gateway mappings; both SAM and Serverless have easy-to-declare abstractions over the resource primitives- this is where the serverless CF output is important to study.