In early 2026 we moved a production serverless application from SST v2 to SST Ion. The application — twelve Lambda functions, an API Gateway, three DynamoDB tables, two SQS queues, and a handful of EventBridge rules — had accumulated enough deployment pain under CloudFormation to justify the rewrite. What we did not expect was how fundamentally different the underlying engine would be. SST Ion is not a version bump. It replaces CloudFormation with a compilation pipeline from TypeScript to Pulumi's Terraform bridge, and the implications for how you build, debug, and reason about serverless infrastructure go deeper than most migration guides cover.
How the Ion Engine Compiles TypeScript to Terraform
The engineering story that matters most is what happens between sst deploy and the moment your resources appear in AWS. Under v2, the framework called CDK synth, producing CloudFormation templates that AWS CloudFormation then evaluated and applied. The pipeline was opaque in two directions: you could not inspect the intermediate representation before it hit CloudFormation, and change set evaluation was slow even for single-resource updates.
Ion replaces this pipeline entirely. When you run sst deploy, the framework executes your sst.config.ts as a Pulumi program. Your TypeScript component declarations — new sst.aws.Function(...), new sst.aws.Bucket(...) — are compiled into a Pulumi resource graph, serialized into a deployment plan, then translated through Pulumi's Terraform bridge into direct Terraform AWS provider calls. CloudFormation is never involved.
The shift produces measurable deployment improvements. Our twelve-function API deployed from cold in approximately 195 seconds under v2. Under Ion, a cold deploy averages 62 seconds across twenty measurements — roughly a 68% reduction. Hot deploys where only one Lambda's code changed complete in 18 to 24 seconds, because Pulumi's resource graph identifies the single changed resource and applies only that update. CloudFormation re-evaluates the entire stack for every change.
The compilation model also means sst diff produces a readable Terraform-style plan before deployment. We run it before every production deploy as a safety check, and it has caught two cases where a configuration change would have replaced a DynamoDB table rather than updating it in place.
The compilation pipeline introduces a state backend dependency that v2 did not have. In v2, CloudFormation managed state implicitly. In Ion, you must configure a Pulumi state backend — either Pulumi Cloud or an S3 bucket with DynamoDB locking. If the backend is unreachable, deployments fail. We hit this during a Pulumi Cloud outage in March 2026 that lasted 14 minutes; our CI pipeline queued deploys until recovery. It is a new failure mode that teams need to add to their deployment runbooks.
Multi-Cloud Support and Where the Seams Are
SST Ion's multi-cloud story is ambitious and still maturing. The framework supports AWS and Cloudflare as first-class providers, letting you define resources on both clouds in a single sst.config.ts file with cross-cloud dependency resolution.
We ran a multi-cloud experiment deploying a Cloudflare Worker that reads from an AWS DynamoDB table and a Cloudflare R2 bucket, with D1 as a secondary store. The component API handled individual resources cleanly — new sst.cloudflare.Worker(...), new sst.aws.Dynamo(...), and new sst.cloudflare.D1(...) all follow the same pattern. The framework generates separate Pulumi stacks per cloud provider, so a Cloudflare-only change does not trigger an AWS deployment.
The seams appear in two places. First, cross-cloud IAM is manual. If a Cloudflare Worker needs to call DynamoDB, you write the IAM access key as a Cloudflare Worker secret — there is no link() call that bridges AWS authentication to Cloudflare. This reflects the reality that no cloud provider supports cross-cloud IAM, not an SST limitation, but it matters if you design a multi-cloud architecture around Ion.
Second, the Cloudflare component surface is substantially smaller than the AWS provider's. As of May 2026, Ion supports Workers, D1, R2, KV, Queues, and Durable Objects, but not Pages, Workers for Platforms, or AI Gateway. For unsupported services, you drop to raw Pulumi resource definitions — functional, but without Ion's ergonomic benefits.
Ion v3 vs. CDK, Terraform CDK, and Pulumi: A TypeScript IaC Comparison
During our v2 migration, we compared four TypeScript infrastructure-as-code options against the same twelve-function serverless API. The comparison revealed trade-offs that documentation alone does not surface.
AWS CDK (v2) produced CloudFormation templates. Deployments for our application took 180 to 210 seconds. The CDK's L2 constructs provided reasonable abstractions for common patterns, but cross-service wiring — connecting an EventBridge rule from service A to an SQS queue in service B — required explicit IAM policy construction that Ion's link() abstraction eliminates. CDK is the most flexible option for teams that need to deploy every valid AWS configuration, but it is the least opinionated, which translates to more boilerplate for common serverless patterns.
Terraform CDK (CDKTF) compiled TypeScript to Terraform JSON with comparable deployment speed — approximately 70 seconds for a cold deploy, since both ultimately call the Terraform AWS provider. The difference was in developer experience: CDKTF requires manual Terraform backend configuration, provider version management, and state locking. SST Ion wraps these concerns inside its CLI, so you write application code rather than Terraform configuration.
Pulumi (native) offered the closest comparison. Ion is built on Pulumi's engine, and a Pulumi program deploying the same resources looks structurally similar. The difference: Pulumi requires explicit IAM roles, policies, API Gateway integrations, and Lambda event source mappings. SST Ion layers a component model that generates these from intent declarations. If Pulumi is assembly for cloud resources, SST Ion is a compiled language where the compiler understands what "this function subscribes to this event bus" means.
The framework that won for our use case was SST Ion, but the margin was narrower than expected. If we needed resources outside Ion's component API — VPC peering, Transit Gateway, AWS Organizations — we would have chosen native Pulumi or CDK. Ion's value is proportional to how much of your infrastructure fits within its component model. For serverless applications on Lambda, API Gateway, DynamoDB, SQS, SNS, and EventBridge, coverage is near-complete. For EC2, ECS, or networking primitives, the gaps grow.
Production Readiness for Teams on v2
The question we hear most from teams on SST v2 is whether Ion is stable enough to justify the migration. After four months of production use across two environments, our answer is conditional: yes for serverless applications that fit within Ion's documented component surface, but with real caveats.
The framework itself is stable. We have not encountered an Ion bug that caused a failed deployment or misconfigured resource since our second week of production use. The Pulumi engine underneath is battle-tested, and the Terraform AWS provider has years of production hardening.
Where the gap exists is in operational tooling. SST v2's Console provided a deployment dashboard, resource browser, and log viewer. Ion's Console, as of May 2026, covers deployment history and resource inspection but not log streaming or invocation metrics — those still require CloudWatch. The SST team has committed to Console parity with v2 by Q3 2026, but for now, you lose operational visibility.
The other consideration is the Pulumi state backend. Pulumi Cloud's free tier introduces an external service dependency into your deployment pipeline. The risk is low — Pulumi Cloud has better uptime than most internal CI systems — but it is a dependency that did not exist under v2. Teams that cannot tolerate it can self-host state on S3 with DynamoDB locking, at the cost of managing that infrastructure.
Originally published at pickuma.com. Subscribe to the RSS or follow @pickuma.bsky.social for new reviews.
Top comments (0)