work project
Healthcare Microservices Platform
Splitting a monolith into twelve services that handle patient data and have to prove it.
- Kubernetes / GKE
- Terraform
- Google Cloud Platform
- Istio
- Helm
- ArgoCD
- Prometheus / Grafana
- Node.js
- React
- AWS Lambda
- Google Cloud Functions
- Took a monolith to 12+ microservices on GKE with Terraform-managed infrastructure and GitOps delivery, cutting infrastructure cost by roughly a third.
- Built the serverless API surface — 25+ endpoints across Lambda and Cloud Functions handling 500k+ daily requests — plus the mesh, network policy, and secret-management layer underneath the services.
- Engineered a medical-notes system with deep multi-level nested forms on a reusable component base, for a healthcare provider's clinical workflows.
What it was
A no-code platform company whose products included clinical tooling for a healthcare provider. The existing system was one deployable that did everything, and the work was to break it into services that could scale, deploy, and fail independently while handling patient data.
What made it hard
The monolith could not scale a part of itself. Traffic on one feature meant provisioning capacity for all of it, which is why the cloud bill looked the way it did. Release cycles were slow and rollbacks frequent, because every change shipped alongside every other change.
Healthcare made the split harder rather than easier. Patient data means encryption in transit between every pair of services, audit trails that survive an auditor’s questions, and access controls that are demonstrable rather than assumed. Doing that once inside a monolith is a middleware. Doing it across twelve services in more than one language is an architecture problem. And the clinical forms themselves were genuinely nasty: multi-level nesting, conditional sections, and clinicians who will not tolerate a form that loses their work.
What I owned
I built the Terraform codebase for the GKE cluster, networking, storage, and IAM, and implemented the service mesh and network policy layer for inter-service communication. I set up the CI/CD pipelines and GitOps delivery, and the monitoring, logging, and alerting stack on top. I also wrote the serverless API endpoints across Lambda and Cloud Functions, and built the medical-notes system and its nested-form component base.
The decision I would defend
We put a full service mesh in, rather than doing mTLS at the library level inside each service.
The mesh is not cheap. A sidecar on every pod costs latency and memory, it is a second control plane to run and upgrade, and it changes the answer to “why did this return a 503” from a question about your application to a question about somebody else’s proxy config. What it bought was mutual TLS, retries, circuit breaking, and per-service network policy applied uniformly across services written by different people in different languages, without touching twelve codebases or trusting twelve teams to get it right. For a compliance requirement, uniform enforcement outside the application is worth a lot more than correct enforcement inside most of it.
Where it landed
12+ services running independently on GKE, infrastructure cost down by roughly a third, 500k+ daily requests served across 25+ serverless endpoints, and a deployment path that no longer required a coordinated release of everything at once.
What I would do differently
I would earn the mesh instead of adopting it. We turned it on before anyone on the team could read an Envoy config, which meant that for several months the security layer was also the thing most likely to break and the thing nobody could debug. At twelve services, mTLS terminated at the ingress plus Kubernetes network policies would have satisfied most of the actual compliance requirement for a fraction of the operational weight. I would reach for a mesh at thirty services, or at the point where a named person owns it.
The other honest miss is that we drew the service boundaries along the module boundaries that already existed in the monolith, because they were there and it made the migration tractable. Some of those were real domain boundaries. A few of them never once deployed independently of each other in production, which is the clearest possible signal that they were one service wearing two hats, and we were paying the distributed-systems tax on them for nothing.