What was on fire
The security team had already bought the product. It had nowhere it was allowed to run.
Cigna has a whole lot of database platforms — Databricks, Teradata, Postgres, pretty much every kind you’d want — and a whole lot of users, and the security team wanted one way to secure all of it. Not just row-level security: column-level too, with policies behind it. The way it had always been done was views — a view over the raw tables for each audience, and a grant on each view. That is cumbersome, and very difficult to maintain over petabytes of data.
Immuta was the answer they had bought — author a policy once and have it hold across the platforms. One example of dozens: some of our clients don’t want anyone offshore reading their data. An offshore employee logs in, their own metadata says they’re offshore, and their query in Databricks comes back with none of those clients’ rows.
I was 50% allocated to the security team. My piece was to get it deployed in AWS: the Terraform around it, the integration with our other platforms, and everything the path to prod asks for — IAM roles from the internal service that vends them, our in-house monitoring and metrics.
Constraint set
The SaaS couldn’t get in. Letting an outside vendor through our external firewalls and every layer after them, down to the database side, is a tough sell. Before the hole there’s legal, networking, and everyone else, and the vendor goes through security reviews and audits of its own. That process exists for a reason — a vendor with a line into your core databases should be reviewed. But we weren’t going to get legal authorization inside the timeframe we needed. For a proof of concept, the process was insane.
The vendor’s documented approach was EKS. The EKS we were allowed to use was a shared enterprise cluster that doesn’t allow persistent volume claims, and Immuta runs a database of its own. A cluster of our own was possible, through a lot of hoops.
And the platforms weren’t ours. We didn’t own Databricks, or any of the other databases. We were a security team that was supposed to help secure them, so every database team had to let us in the front door. None of us was proficient in Kubernetes, either, and with limited access to our own AWS accounts, everything went through Terraform.
System diagram
Where it could run, and the one piece that never moved.
Architecture decisions
- Self-host the proof of concept instead of waiting on the SaaS. Immuta can run outside its SaaS, so the question became where. Rejected: the SaaS path, which needed a firewall hole, a vendor review, and legal sign-off before we’d learned anything.
- Move the state out first. The vendor’s install ran its database inside the cluster, on a persistent volume the shared cluster wouldn’t give us. I separated the database out onto Amazon RDS for PostgreSQL, changed the configuration to point at a Postgres the charts didn’t ship, and worked out how authentication would reach it. The idea was never to keep the proof-of-concept box forever. With the state outside, any cluster was a connection string away. Rejected: fighting the shared cluster for volumes, or standing up an EKS cluster of our own through the hoops.
- Run two tracks. While the EKS approvals crawled, I put K3s on a single large EC2 instance, which I could spin up with no problem. Then I worked backward from the vendor’s Helm charts to see how they wired everything for EKS, and rebuilt it for ours. I spent a lot of time with the vendor’s engineers, and they didn’t have a great solution for a cluster that allows no volumes. Their next major Helm chart, in May 2024, stopped shipping a database at all and told customers to bring a managed PostgreSQL such as RDS. The older chart could already point at an outside database. The new one made it the only way.
-
Prove it on their own filtering before asking them to switch. The database teams wanted
to know the performance implications and how it behaved in different scenarios. I wrote test scripts
that ran their existing row- and column-level filtering side by side with Immuta’s. In some of those
tests Immuta was significantly faster. One case was a lot slower: a
SELECT *with noWHEREclause, where Immuta evaluated every row behind the scenes to see whether it hit a policy — on databases our size, a very real problem. Their answer was that their reporting users run exactly that and have to keep running it. Mine was to find the reports doing it and bring them up to best practice. They still didn’t like it.
Not again: don’t bring a new control to platforms you don’t own until someone above those teams can make the call.
Recovery / operate path
We started at the beginning of 2024, and the year that followed went to red tape and a learning curve, not to the product. Kubernetes first, then Kubernetes inside AWS, then all the Terraform around it. Then the EKS approvals, and the path to prod. There’s always a feedback loop: an architecture review comes back with “we need X, Y, and Z,” and by the time you’ve made the change and gotten back on their schedule, one cycle runs 3–6 weeks. The Databricks integration was the easy part.
The plan held. The lower environment moved from the K3s box to EKS by changing the connection string — same database, data intact — and it worked exactly as planned. Production went up on the shared EKS, its database on RDS, around the beginning of 2025.
Where it reached in production, as far as I know:
| Platform | Enforcing in prod | What the vendor’s own docs show |
|---|---|---|
| Databricks | Yes — the one I know for sure | Policies compile into Databricks’ own row filters and column masks |
| Teradata | I’m not sure | A legacy database in the 2025.1 release. The new connector (November 2025) governed access to whole views, and row filtering and masking came in March 2026 |
| PostgreSQL | I’m not sure | Listed among the legacy databases in the 2025.1 release |
Teradata does row-level security on its own — what lagged was the connector, not the platform.
No count of policies, users, or queries. No numbers from the performance tests — only which way each case went.
What changed after
The database teams dragged their feet for months: “we’re waiting for performance testing,” then “we’re waiting for validations.” They still do. We were doing what the organization wanted, and there was no one in leadership above those teams who could force the decision. There’s a lot of inertia in how things used to be done.
Then the reversal. Once it was in production, leadership wanted the features the vendor ships to its SaaS customers first — Immuta’s own documentation says SaaS deployments “get features first.” So the self-hosted deployment is being converted to the SaaS that couldn’t get through the firewall for a proof of concept. I’m no longer on that team, and I can’t tell you how it’s going.
At the time, self-hosting was the right call. We didn’t really have any options. You don’t move mountains to punch a hole in a firewall for a proof of concept. Once it was in production it wasn’t a proof of concept anymore, and asking for the SaaS was asking for the same functionality, not for an experiment.
Anonymization notes
The client ships by name; the people do not. The security team, the database teams, my leadership, and the vendor’s engineers appear as roles. No client of Cigna’s is named — the offshore rule is described by what it does. Immuta, Databricks, and Teradata are named because the story turns on them. What this page says about Immuta’s Helm charts, its connectors, and its SaaS comes from Immuta’s own public documentation, not from inside the engagement. The internal service that vends IAM roles is described by what it does. Withheld: team and cluster names, the number of policies, users, and queries, and the test results beyond which way each case went. The dates are my own recollection. Stack footnote: Immuta self-hosted from its Helm charts — K3s on one EC2 instance for the lower environment, then Amazon EKS — its database on Amazon RDS for PostgreSQL, Terraform throughout, policies enforced in Databricks.
Who this is for
- A security team that bought a control for platforms it doesn’t own.
- A vendor install that assumes a cluster your platform team won’t give you.
- A proof of concept that can’t justify a firewall hole into the database zone.
- A leader whose new control is being waited out by the teams it’s meant to cover.
Related systems
The path to prod that carried the first workload off Pivotal Cloud Foundry into AWS, then eight more
Pivotal Cloud Foundry, Terraform, Jenkins, Amazon CloudFront, AWS Lambda, Amazon ECS, Amazon RDS, RDS Proxy, Okta
Health insurance · Cigna · operating
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
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.