Senior Infrastructure Engineer
I build and operate the boring, reliable systems that let other engineers ship — Kubernetes at fleet scale, Infrastructure-as-Code discipline, GitOps delivery, and CI/CD that engineers actually trust. 10+ years running production platforms real people depend on.
I started as a Linux systems admin managing thousands of physical servers, moved into cloud and DevOps as the industry did, and today spend most of my time running multi-tenant Kubernetes platforms for regulated, high-availability workloads. My work sits at the intersection of platform engineering, site reliability, and internal developer experience — with a particular interest in observability that has a signal-to-noise obsession, not just dashboards for their own sake.
The lens I bring to infrastructure is that it should feel invisible when it works, and it should teach you something when it breaks. I treat internal tooling as a product — measured by adoption, iterated on real feedback — and I use modern AI tools daily as a force multiplier for debugging, log analysis, and toil reduction, with the discipline that AI proposes and the engineer commits. Based in Pune, India, fully remote and async-friendly across US, LATAM, and European time zones.
Six capabilities, one habit — treat infrastructure like a product, and use AI as a force multiplier without touching production trust.
Multi-tenant Kubernetes platforms across hundreds of clusters and services — EKS lifecycle, Karpenter autoscaling, Istio service mesh, and progressive delivery (canary, blue-green) via GitOps.
8+ years of Terraform — reusable module composition, remote state with locking, and drift detection across hundreds of stacks. Also comfortable with Pulumi, Ansible, and CloudFormation-compatible patterns.
Reusable CI/CD workflows serving hundreds of microservices via language-agnostic caller patterns. SHA-pinned actions, OIDC cloud auth, image scanning that gates criticals — no static keys, no snowflake pipelines.
Alert catalogue design with an anti-noise obsession — every alert actionable and tuned against real historical data. 24x7 on-call, structured incident response, and blameless postmortems that drive systemic fixes.
Daily use of Claude, Cursor, and MCP-based automation — log analysis during incidents, infra boilerplate matched to codebase conventions, and low-risk toil automation. AI proposes, the engineer commits.
Security gates built into the pipeline, not bolted on after — Trivy image/dependency scanning, OIDC-only cloud auth with zero static keys, least-privilege IAM, and secret rotation. Operated under SOC 2 and PCI-DSS regimes.
Same pattern behind every platform I run: code triggers CI, a security gate scans it, Terraform plans the change, AWS and Kubernetes apply it, and observability watches it land.
Security Scan = Trivy image/dependency scanning + OIDC-only cloud auth, no static keys. A critical finding blocks the pipeline right there — Terraform never gets to plan a change built on a vulnerable image.
Five things running on autopilot right now, doing the toil so engineers don't have to — including the one that says no.
Real production work, anonymized — the platforms and pipelines I've designed, built, and operated.
Onboarding a new tenant meant assembling an entire footprint by hand — AWS account, VPC and networking, EKS cluster, container registry, git repo, IAM roles, monitoring integration, ArgoCD registration. Every new tenant took days of coordinated manual work across teams. For a platform expecting to scale into dozens of regulated financial customers, that model doesn't survive contact with growth.
Built a Terraform-driven self-service workflow that provisions the entire tenant footprint from a single command. The design decision worth naming: account-per-tenant isolation was chosen over namespace-per-tenant, even though namespace isolation is cheaper. For regulated financial workloads, account-level isolation gives clean blast-radius boundaries, simplified compliance scope per tenant, and per-tenant data residency without engineering acrobatics. ArgoCD ApplicationSets handle add-on and configuration fanout so the fleet stays consistent as it grows.
Hundreds of microservices spread across languages and repositories, each carrying its own copy of build, test, and deploy pipeline logic. Small changes to security or deployment policy meant hunting through hundreds of workflow files, drift accumulated silently, and the security posture was only as strong as the least-maintained pipeline. That pattern doesn't scale past a small number of services.
Built reusable GitHub Actions workflows that every service repository calls through a language-agnostic, Makefile-based pattern — so per-service repos declare intent (build, scan, deploy) but the actual logic lives in one place. The security work went in the shared layer: SHA-pinned actions preventing supply-chain drift, OIDC-based cloud authentication eliminating static access keys entirely, Trivy image scanning that fails builds on critical vulnerabilities, External Secrets Operator syncing runtime secrets from AWS Secrets Manager. Reduced local iteration friction with the act tool so engineers could test workflow changes on their laptop instead of pushing and waiting.
Migrate 40+ regulated workloads from a legacy environment to a modern Kubernetes-based platform. The customer connectivity constraint made this hard: bank customers connected via legacy VPNs with fixed endpoints and long change-approval cycles. Asking 40+ banks to coordinate network changes on the platform's timeline was a non-starter — the obvious cutover patterns all required customer cooperation on someone else's schedule.
Rather than force customer network changes, architected an ECS-based transparent proxy layer that bridged legacy VPN connections to the new EKS clusters through VPC endpoints. From every customer's perspective, nothing changed — same endpoints, same source IPs, no coordinated cutover window. Workloads migrated in parallel behind the proxy layer, then the legacy platform was decommissioned once traffic had fully shifted. The tradeoff worth naming: the proxy layer added real complexity and operational surface area during the migration window, but that was a cost worth paying to avoid 40+ separate customer change requests.
A monitoring stack across Prometheus, AlertManager, Grafana, Sysdig, and CloudWatch had accumulated years of drift — duplicate alerting rules, false-RESOLVED conditions, thresholds set against baselines that no longer applied, and enough noise that on-call engineers had stopped trusting the pager. Alert fatigue isn't a nuisance in production infrastructure; it's a reliability risk, because engineers who stop trusting alerts miss the real ones.
Full audit of alert configurations across the fleet. Killed duplicate PrometheusRule objects, fixed alerting logic that produced false resolutions, and rebuilt the catalogue around three principles enforced through code review: every alert must be actionable (map to a specific human action), every alert must be symptom-aligned (map to real user impact, not raw infrastructure counters), and every threshold must be tuned against real historical data rather than round-number guesses. Designed a phased auto-remediation roadmap using Robusta for well-understood patterns like OOM loops and CPU throttling — the humans handle the interesting incidents, automation handles the repeats.
Development and pre-production clusters running 24x7 despite being used only during business hours, driving unnecessary cloud spend that grew linearly with tenant count. A recurring cost pattern everyone knew about but nobody had time to fix.
Built a Lambda-EventBridge automation that scales dev cluster node groups to zero outside business hours and back up on-demand when engineers log in. Combined with namespace-level tagging to enable accurate cost attribution across dozens of tenants, so cost visibility grew with the platform instead of degrading with it. The build-vs-buy call: off-the-shelf solutions existed but locked into their own workflow, whereas the custom Lambda approach was ~200 lines of Python and integrated cleanly with the existing IaC.
A platform-wide mutual TLS initiative needed a certificate authority architecture. The default "secure" answer — a two-tier CA hierarchy — came with a real, non-trivial monthly cost increase over a flatter single-tier setup. This was a decision leadership needed to make with full visibility, not one that should be made silently by an engineer who preferred one option over the other.
Modeled three concrete options — single-tier CA, standard two-tier hierarchy, and a two-tier hierarchy with an offline root — and presented the actual monthly dollar delta between "secure" and "more secure" alongside the security posture each option represented, framed as a cost-versus-blast-radius tradeoff rather than a technical recommendation. The winning insight: the two-tier-with-offline-root option came in at roughly the same monthly cost as the single-tier flat setup, because the offline root eliminated ongoing subordinate-CA idle costs — so the "more secure" option turned out to be the fiscally reasonable one too, but only after real modeling made that visible.
Sev-1 incidents kept recurring with the same gap: the right people weren't getting looped into the incident channel or the postmortem in time — not from neglect, but because remembering exactly who owns which product area under pressure doesn't scale as a human process. Another wiki reminder wasn't going to fix a problem that was fundamentally about relying on human memory at the worst possible moment.
Instead of another process document, built the fix into the ticketing system itself: the moment a ticket crosses into the highest severity, it automatically posts a checklist mapped to a maintained product-to-owner table — so the right names show up without anyone needing to remember them. The ownership table is the single source of truth, versioned in git so ownership changes go through review like anything else. The principle: prefer system-level fixes over process-level fixes for anything that has to happen reliably under pressure.
Cloud environments accumulate waste quietly — stopped instances, unattached volumes, empty load balancers, unused databases, orphaned snapshots — and manually auditing all of it across many separate customer environments isn't something anyone can realistically do by hand on a recurring basis.
Built a Python-based audit tool covering roughly 20 resource categories across compute, networking, storage, and database layers. Accepts a single environment ID or a full list of them, runs the same structured checks against each, and produces a clean categorized report. Ran read-only against production and included per-category confidence levels, so obvious waste (stopped instances for 90+ days) got flagged separately from potential-but-unsure findings (databases with low activity) instead of dumping everything into one undifferentiated list.
A partner integration required encrypted files, uploaded via SFTP, to end up decrypted in a specific storage location for a downstream application. This was being handled with manual aws s3 cp commands every time a new file landed — functional, but a recurring manual chore with an unstated deadline attached to every drop, and a single point of human failure.
Replaced it with an event-driven pipeline: a new file landing triggers a decryption function that reads the file into memory — deliberately never writing decrypted plaintext to disk — decrypts it with a private key held in a secrets manager, and writes the result to its destination, with failure alerts wired to open a ticket automatically. Used a container-based function rather than a zip-and-layer function specifically because the decryption library needed a real system binary dependency, far more reliable to ship in a container image than to hand-assemble as a layer.
A compliance-audit SaaS product on on-premise infrastructure needed to move to AWS — without weakening its posture, since its own customers were subject to SOC 2 and PCI-DSS audits. The existing infrastructure had no IaC at all: everything was hand-configured on physical servers, so there was no documented ground truth to migrate from.
Three phases: capture the existing on-prem architecture as Terraform first (which surfaced multiple undocumented dependencies), rebuild the same architecture on AWS with proper VPC/EC2/ELB/Auto Scaling/S3/Lambda/API Gateway foundations, then cut over customer by customer with rollback paths preserved. Compliance was designed in from day one — Rapid7 InsightIDR for SIEM, Nexpose for vulnerability scanning, Palo Alto and Fortinet firewalls managing the hybrid perimeter through the transition.
Operating an enterprise datacenter with 10,000+ physical servers across IBM, Dell, and HP hardware plus EMC, NetApp, and Hitachi storage. At that scale, coordination becomes as much a failure mode as the hardware itself — knowing what depends on what, who's on point, and how to fail over cleanly matters more than any individual tool.
Ran L2 operations with 24x7 on-call coordinated through a formal Emergency Response Team. Standardized Linux service configuration (NFS, FTP, Postfix, DNS, SMTP) across RHEL, CentOS, SUSE, and Ubuntu so runbooks worked regardless of which OS a given customer's stack ran. The real reliability gains lived in preventive work — capacity forecasting, hardware refresh planning, HA cluster validation — ahead of incidents rather than after them.
Hand-configured infrastructure meant "what's actually in production" and "what's in the documentation" were reliably different things — and nobody was surprised by that, which was the deeper problem. Without a source of truth, every incident started with archaeology, and every change was riskier than it needed to be.
Treated the transition to IaC as a cultural project, not a technical one. Captured existing state in Terraform without changing anything first, so code matched reality at t=0. Introduced drift detection so hand-changes to the console got flagged within a day and remediated through PR. Console access became break-glass only, tracked with reason and duration. The hardest part wasn't the tooling — it was building the habit that the code is the truth.
A cloud estate with a hand-built Kubernetes cluster, no infrastructure code, no Helm charts, and deployments done by imperative apply with in-place text substitution of image tags — no rollback, no drift detection, no image scanning. Six weeks to build a production-grade platform and migrate the first real application onto it. A short timeline forces real engineering choices; every abstraction has to earn its place.
Terraform provisions the cluster, node groups, workload identity, add-ons, DNS, and the GitOps controller in a single apply. The GitOps controller then deploys the full platform stack — Istio in ambient mode (chosen over sidecars because per-pod overhead is hard to justify on a small node count), ingress, autoscaler, secret operator, monitoring — in dependency order via sync waves. Applications deploy by pipeline: build, scan, push an immutably tagged image, open a merge request against the GitOps repo. Merging is the deploy. Persistent resources (state bucket, registry) deliberately sit in a separate lifecycle from cluster resources, so a full teardown can never destroy images or state — that's what makes destroy-and-rebuild routine instead of terrifying.
Every application's authentication depended on a single hand-configured VM running several parallel installs of the same software, with no repository describing what was actually live — its working tree held uncommitted local edits. The job: containerize it without breaking any downstream application's login.
Rebuilt the image with a pinned official base, multi-stage, non-root, key material mounted at runtime, and certificate validation restored on the directory-service client (it had been silently disabled). Replaced hostname-substring environment detection — which defaulted to production for anything unrecognized — with explicit configuration. Extracted live config by instantiating the application's own config class rather than transcribing values, guaranteeing an exact match to what the previous deployment used. One correction along the way: the initial plan was to generate a fresh signing keypair for the new environment — that would have broken login, since the same key both signs assertions and is what they're encrypted to. Caught by comparing the committed certificate against the configured value byte-for-byte, and reused the original instead.
A self-hosted community-edition version control server with no enforced code-owner approvals and no standard for how repositories were created — every new repo was a fresh chance to forget branch protection, environment branches, or permission groups.
Built a pipeline that provisions a repository — settings, permission groups, environment branches, branch protection, initial files, review gate — in one trigger. The hard part: the community edition doesn't enforce code-owner approvals (a paid-tier feature). Recreated the equivalent as a pipeline job that queries the review API and fails when the only approval belongs to the author. Along the way, API writes against freshly created projects returned success but silently didn't persist, only when called from inside the CI runner — traced to the runner resolving an internal address that reached a different routing path where the new project hadn't yet propagated. Fixed with `git push` for the initial commit (a different network path) and moving config into a separate pipeline stage so scheduling provided the propagation delay, instead of papering over it with a sleep.
Inherited a repository with committed secrets accumulated over years — the kind of situation where "we should rotate those" has been a to-do for so long nobody remembers what was actually leaked. Rotating everything blindly is expensive; rotating nothing is negligent.
Enumerated committed secrets across the repository's history and classified them by blast radius rather than by "is it a secret." Split findings into three tiers: signing material (rotation requires coordinating every relying service — expensive but critical), routine live-service credentials (rotate promptly), and retired/test-only credentials (revoke, low urgency). Moved credentials staying in service to a managed secret store with operator-based sync, so workloads no longer held their own cloud credentials.
14 Sev-1s and deep-dive investigations, anonymized, spanning about five months of production work. Root cause, fix, and lesson — the short version here, the full RCA one click away.
Login looped forever after a platform migration. Four hypotheses, each disproved with direct evidence — the real cause was a browser capture showing not one Set-Cookie header in 90 requests.
When source-level reasoning stalls, go get a direct capture of what's actually on the wire.
Read the full story →Where AI genuinely sped up a six-week platform build, and the five specific times I had to catch it — a signing key that would've broken auth, a chart interface it imagined, a stale branch it trusted.
Verify anything load-bearing by running it. Keep the architectural calls for yourself.
Read the full story →A VPN flap that should have self-healed in minutes instead cascaded into a multi-hour outage — three separate factors compounded, not one.
Default settings are load-bearing until the day they aren't.
Read the full story →AWS called a VPN outage self-resolving. My own BGP route snapshots proved the routes were gone before AWS's maintenance window even started.
Don't let the vendor write the incident timeline.
Read the full story →A pod kept crashing behind perfectly reasonable try/catch blocks — because the real failure happened somewhere try/catch structurally can't reach.
Async Promise executors can hide exceptions from every try/catch around them.
Read the full story →ArgoCD self-heal and Kubernetes' garbage collector raced each other over a manually deleted Deployment — twice, on two different apps.
Pause the automation before you touch a self-healing resource by hand.
Read the full story →A vague "things feel slow" complaint, no red dashboards anywhere. Digging anyway turned up four distinct, real problems.
Four bugs is not one bug wearing a trenchcoat — but it's tempting to think so.
Read the full story →A routine EKS upgrade started crash-looping a service, 64ms after every request. The upgrade wasn't the bug — a hardcoded timeout was.
Your upgrade isn't the bug — it's the flashlight.
Read the full story →OTP auth failed across several tenants at once. One tempting shared cause — until the timestamps for one tenant didn't fit at all.
Correlation isn't causation, even when the timing looks suspicious.
Read the full story →A "just wire up TLS" ticket turned up zero real certificate infrastructure — just a self-signed issuer never meant to face real clients.
When "just wire it up" is secretly an architecture decision, stop and surface it.
Read the full story →Investigating an out-of-order email trigger turned up something worse: an automation that could move real production money had zero sender validation.
"It's always worked correctly" is not evidence an authorization boundary exists.
Read the full story →A banking connector returned 403 Forbidden — with a response body that said InternalServerError. The mismatch was the actual clue.
When the status code and the body disagree, believe the disagreement.
Read the full story →A GitOps app sat on a stale image for half a day. Two real bugs turned up along the way — neither one explained it. The answer was in last week's commit history.
Check what changed, not just what's currently configured.
Read the full story →A noisy, zero-action alert couldn't be filtered where it seemed like it should be — that layer simply didn't support filtering at all.
When the obvious fix layer can't do it, trace the pipeline's real order of operations.
Read the full story →A service mesh's control plane had moved ahead of a subset of workload sidecars still on an older Envoy proxy. Newer config fields got rejected outright by the older proxies, which then failed health probes and restarted repeatedly. Fixed by identifying the exact 10 workloads on the stale sidecar version and rolling them.
An Istio AuthorizationPolicy kept failing to sync because a template rendered an empty rule as null instead of an empty array. The first fix patched the values file; the real fix — found after auth broke for real users post-merge — guarded the field at the Helm template level so it only renders when populated.
A file-processing integration used a single shared external cloud account with bucket-wide read access across all customers. True per-customer isolation required a separate storage bucket per customer, not simple folder separation — a subtle but important distinction for any multi-tenant vendor integration.
A production database CPU spike wasn't application load at all — traced to a data-governance/cataloging tool performing thousands of sequential table scans per second against a metadata table it wasn't supposed to be hammering that hard.
An RDS storage alert fired, looking urgent. Actual disk usage was around 7% — the alert was triggered by an autoscale threshold setting, not real capacity risk. Turned into a right-sizing recommendation that also cut monthly cost.
A flood of simultaneous "load balancer unhealthy" and "VPN both tunnels down" alerts fired across many unrelated accounts in the same region within minutes of each other. The pattern itself — many unrelated customers, same failure mode, same window — was the tell: a regional provider-side networking failure, not independent per-customer problems.
Ahead of a production cutover, a business-reported "calls per day" figure turned out to be a business-layer metric, not the proxy-level number it was being used as — worth catching before it shaped a capacity decision. Separately, a stuck NotReady node was cordoned and force-replaced, which also surfaced that the node group had zero scaling headroom left (maxSize=4, desiredSize=4) — a second finding worth its own follow-up.
A recurring pattern worth naming: real production debugging sessions — alert scripts, threshold decisions, actual incident tickets — kept getting formalized afterward into structured runbooks, complete with the real alert names, thresholds, and escalation paths used in production. Documentation as a byproduct of good incident hygiene, not a separate chore nobody gets to.
Deleting a resource tied to a provider whose API keys had expired meant every plan or destroy tried to refresh it first — authenticating with credentials that no longer worked, failing before Terraform could even get to deleting anything. terraform state rm was the tempting shortcut; the safer fix addressed the provider block itself instead of reaching for state surgery.
A terraform destroy failed with ResourceInUseException on a Route53 Resolver endpoint. AWS enforces a strict dependency chain here — disassociate the rule from the VPC, delete the rule, then delete the endpoint. Terraform was correctly refusing to proceed out of order; the fix was doing the teardown in the order AWS actually requires.
While investigating a stale-data report, a customer pasted log output containing real names, tax IDs, and account balances directly into a shared ticketing tool. The technical issue (a stale cache downstream) was minor; the real finding was stopping to flag the plaintext PII exposure and push for redaction in the health-check tooling itself.
A customer's alarming metrics screenshot turned out to match a known, already-fixed cause exactly — restarts isolated entirely to the monitoring stack's own pods, correlating with known restart windows. Rather than assume, I cross-referenced hour by hour, confirmed their query was correct, and handed back a refined query that excludes a namespace they don't own.
Ahead of a real-time payments launch, an internal architecture walkthrough surfaced the actual biggest launch risk: a partner's decision system took 8-10 seconds to wake from idle — well past the payment network's strict cancellation deadline. Distilling a long meeting into one prioritized risk, instead of a flat transcript, was what made the risk actionable.
With automatic node provisioning temporarily off, a stuck pending pod needed a manual node group scale-up — done deliberately in pairs, to preserve even distribution across both availability zones instead of accidentally concentrating capacity in one.
A new Apple Silicon machine's package manager broke with built for x86_64 errors — two separate installs, one for Intel and one for the native chip, fighting over the same shell config. Diagnosed down to the architecture mismatch, then migrated safely by backing up what was installed before removing anything.
A public government data API was silently truncating its bulk export, breaking a compliance-dependent downstream service. Finding the right support channel, writing a reproducible bug report, and leaving a clear handover plan — including how to detect if they'd silently fixed it — closed the loop on an escalation with no technical point of contact on the other end.
A network-level timeout (no response) and an active connection reset (the far end actively rejecting the connection) look similar but mean different things. Reading it correctly here pointed the investigation at the customer's own core banking infrastructure, and shaped exactly what to ask their team about recent firewall or certificate changes.
A nicely formatted internal document reportedly lost its formatting when pasted into the team wiki. Before reaching for a more complex export format, the right move was pausing to clarify exactly what had happened — a plain document paste worked fine all along. Not every reported bug needs a technical fix; some need one clarifying question.
During a live "online banking is down" incident, the same health-check output surfaced a missing secret breaking one banking partner's auth, an unrelated cancellation exception in a message-processing service, and several false-positive "errors" that were just log-level noise — three genuinely separate problems that had to be triaged and untangled in real time, not treated as one.
Verify on Credly →
Verify on Credly →
Verify on Credly →
No public digital badge for this one
I write about infrastructure problems I've solved and lessons learned along the way. 17 posts and counting.
Login looped forever after a migration. Four hypotheses, each disproved with direct evidence — the real cause was zero Set-Cookie headers in a 2.7MB browser capture.
Read more →Where AI genuinely sped up a six-week platform build, and the five specific times I had to catch it being confidently wrong.
Read more →A routine TLS ticket turned up zero real certificate infrastructure — just a self-signed issuer never meant to face real clients.
Read more →A VPN flap that should have self-healed instead cascaded into a multi-hour outage — three factors compounded, not one.
Read more →AWS's dashboard said a VPN outage self-resolved. My own BGP monitoring data said otherwise — and won the argument.
Read more →What I learned operating a fleet of k3s, k8s, and EKS clusters for banking clients — from GitOps workflows to upgrade strategies.
Read more →An async Promise executor anti-pattern turned a routine API failure into an unrecoverable crash, invisible to every try/catch.
Read more →ArgoCD self-heal and Kubernetes' garbage collector can race each other and deadlock a Deployment — a runbook for when it happens.
Read more →ATS Cloud Solutions helps startups and enterprises modernize infrastructure with AWS, Kubernetes, Terraform, GitOps, and 24/7 platform operations.
End-to-end cloud and platform engineering services that keep your infrastructure secure, reliable, and ready to scale.
Design and build secure, cost-efficient AWS environments tailored to your workloads and compliance needs.
Learn more →Deploy, scale, and operate production-grade Kubernetes clusters with EKS, Helm, and GitOps workflows.
Learn more →Automate CI/CD, infrastructure provisioning, and deployments with Terraform, GitHub Actions, and ArgoCD.
Learn more →The technologies and credentials behind the platform engineering work.