What was on fire
Express Scripts was still running its workloads on Pivotal Cloud Foundry. Cigna had bought the company, and its estate was AWS-native. My manager brought me back from a startup in December 2020 to get us integrated back into AWS: proofs of concept first, because the team was not well aware of AWS, then teaching a clinical platform’s team what I had done and why things worked the way that they did.
Nothing broke because of the migration. What was complicated was the processes we had built around PCF. Every repo carried a manifest file — tightly coupled to a custom Jenkins — that did a lot of the work for us. Teams deployed lots of infrastructure by convention and never looked underneath it. That convention had been absorbing infrastructure for a workforce hired to write Java. All of it changed the moment the target was AWS and Terraform, with every team responsible for its own.
Constraint set
The estate was not mine to design. Cigna had built it before the acquisition — an account per environment, directory groups mapped through SSO, least-privilege IAM roles vended in, and no route to account-admin in a production account. I inherited all of it and had to land inside it. PCF had also been running our databases, our Redis, and our configuration, and every one of those needed an AWS shape.
The two sides had hired for different things. Cigna’s culture was engineers knowing the full stack their technology is built on. On the Express Scripts side, hiring had been for Java — people brought in to solve business problems, not to own the infrastructure underneath them. So there was a large learning curve: understand what the AWS services do, then bundle them together and ship them with Terraform. This was pre-AI. All of it was manual.
System diagram
Architecture decisions
- Re-sort by workload shape instead of lifting containers across. Rejected: moving PCF containers over as containers. Some teams did end up on EKS, which in and of itself is a real beast to manage and maintain — Cigna ran shared clusters for it, and I was not a part of that.
- Every team owns its Terraform. No golden wrapper. Some teams tried to build one: an AWS-side convention layer so Java-only developers would never touch Terraform, doing the same job the PCF manifests had done. In theory it would work well. The problem is that your workforce isn’t growing out of that. My leadership wanted us taking full advantage of the full AWS stack, so building that capability was my job. That golden wrapper never worked, and people just eventually learned.
- Teach the enterprise CI to run Terraform rather than route around it. Jenkins could not run Terraform at all, so we built that capability inside Jenkins. There was no way around it — in an estate like this you can’t deploy from your own machine, because you don’t have access to the AWS accounts.
| On PCF | Landed on | Why |
|---|---|---|
| Static-HTML containers | CloudFront | — |
| Stateless services | Lambda | Could be made stateless |
| Stateful services | ECS | Couldn’t be made stateless |
| Databases | RDS, RDS Proxy where it had to scale | RDS Proxy added only where scale required it |
Not again: don’t put a convention layer in front of a platform your teams have to learn.
Recovery / operate path
The first workload took over a year. Almost none of that was the technology.
The path to prod was ten stations, and every one of them had to be learned, fixed, or built. Getting started meant approval to create the AWS accounts, a directory group on our side that didn’t carry the same permissions as Cigna’s, and networking between two sets of data centers so an AWS workload could reach on-prem. Then Okta with SAML into AWS, which wasn’t working with our directory accounts. Then the architecture review board — get on their schedule first, bring diagrams that need to look a very specific way with the right colors, and then they review your architecture in detail and send you back with changes.
Then a test account we could deploy into but held no account-admin in — an ugly situation, solved by vending least-privilege roles into it, which was a journey in itself. And Jenkins, which couldn’t run Terraform yet. Last: security and game-day tests validating that the monitoring was in place and things were locked down, a business approval, a production account, the roles loaded, deploy. That is what I invested about a year in.
Once it existed, the full path to prod on a new project took about six weeks. That was the fastest I could do it. I ran eight of them through — some moved over, some built new. Not bad in corporate terms.
The clock is the only number I have. No cost figure, no defect rate, no availability claim.
What changed after
Infrastructure stopped being something a manifest file did for you. Teams own their Terraform now. That is the part that outlasted the migration. Engineers got hungry to do more AWS work and to grow their careers, and that is what helped adoption — not a wrapper. Jenkins is on its way out too, replaced by GitHub Actions.
PCF is completely retired. The desire for on-prem didn’t leave with it: workloads that couldn’t move to AWS got OpenShift clusters, with scripts that translate the old PCF manifest files to run there. That wasn’t my project, and it turned out to be a pretty solid one. It also keeps the old convention alive, which kind of defeats the purpose of going cloud-native.
Anonymization notes
Both companies ship by name — Express Scripts, and the Cigna estate it moved into. The people do not. No internal team or platform names, no account or ticket identifiers. The internal service that vends IAM roles is described by what it does, not by what it is called. The eight projects are not named and are not described individually. The numbers are rounded as I gave them: over a year for the first workload, about six weeks at best afterward, eight projects. Product names stay: Pivotal Cloud Foundry out, AWS and Terraform in, OpenShift for what stayed behind. Stack footnote: Pivotal Cloud Foundry, Terraform, Jenkins, CloudFront, Lambda, ECS, RDS with RDS Proxy, Okta SAML.
Who this is for
- A team being folded into an acquirer’s cloud estate it didn’t build and can’t change.
- A deploy convention that has been owning infrastructure for developers who never had to learn it.
- Anyone budgeting a first cloud workload as a technology project.
- Leadership choosing between a wrapper that hides the new platform and a workforce that learns it.
Related systems
A policy engine's database moved to RDS so the cluster under it could change with a connection string
Immuta, Databricks, Teradata, PostgreSQL, Amazon EKS, K3s, Amazon EC2, Amazon RDS for PostgreSQL, Helm, Terraform
Health insurance · Cigna · superseded
A custom Jenkins with a thin per-repo manifest over a shared library, replacing ticket-driven manual deploys
Jenkins, Jenkins Pipeline shared library, Per-repo manifest + Jenkinsfile, Remedy, .NET on-prem, Kubernetes on-prem, Pivotal Cloud Foundry
Pharmacy benefits · Express Scripts · superseded
More systems
A review-board prototype built in two weeks from the team's own screenshots
React, Node.js, TypeScript, SQLite, Amazon ECS, Cursor, Vercel AI SDK, LiteLLM, Playwright
Newer · Sep 2026
Pre-rendered listings for crawlers after a move to React left Googlebot with a render job
React, AWS Lambda, Headless Chromium, Amazon CloudFront, Amazon S3, Amazon SQS, Amazon ElastiCache
Older · Sep 2026
Start
I’ll tell you in about a day whether I’m the right person. The first conversation is fit, not a free architecture review.