BDIPlus Labs
Software Engineer 2
June 2025 - Present · Bengaluru, India
Backend and platform work across a regulated enterprise API estate and an internal product. Most of my time goes to making a large number of services behave like one coherent system.
- Python
- Java 21 / Spring Boot
- Go
- Kong
- PostgreSQL
- Kubernetes
- AWS
- Dynatrace
- Artifactory
Client · PrudentialAPI modernization across a 175-service estateStandardizing how an enterprise builds, deploys, secures and observes services, so 175 of them stop being 175 different decisions.
- services & packages
- 175
- clusters
- 6
- primary runtimes
- 2
The problem
A large service estate had grown one team at a time. Every service shaped its own request and response contracts, its own audit logging, its own internal dependencies, and its own approach to authentication and rate limiting. Deployment and testing were per-team rituals rather than a shared workflow, which made governance, review and migration expensive in a regulated environment.
What I built
- Kong API Gateway authentication, authorization and rate limiting for client-exposed services, rolled out across 175 services in 6 clusters with per-cluster resource maps behind a single ingress.
- Automated OpenAPI spec-driven deployment: specs generated and tested against the internal test framework, then raised as PRs into the architect review flow for every client-facing API.
- A migration framework with Artifactory-published internal dependencies enforcing uniform audit logging and response structures.
- Migration of the priority services onto standardized Python and Java 21 Spring Boot.
- The Transactional Outbox pattern with Dynatrace tracing and S3 log archival, for reliable and auditable event delivery between services.
- An extension of the Kong template from JSON-only to both JSON and XML.
Engineering decisions
- Problem
- Authentication, authorization and rate limiting were re-implemented per service, so a policy change meant touching every repository.
- Decision
- Push cross-cutting concerns to the edge and let Kong own them, leaving services responsible only for domain logic.
- Implementation
- Per-cluster resource maps behind a single ingress, with authentication, authorization and rate-limit policy configured at the gateway rather than in application code.
- Result
- Policy became a gateway concern with one place to change, and new services inherited the security posture instead of re-deriving it.
- Problem
- Clients could not depend on response or error shape, and audit trails differed enough that review was manual.
- Decision
- Make the contract the artifact: spec-first OpenAPI, a shared response envelope, and a standard audit-log structure distributed as internal packages.
- Implementation
- Standardized dependencies published to Artifactory and consumed by Python and Java 21 Spring Boot services, so the shape is inherited rather than copied. Spec changes are generated, tested and raised as PRs into the architect review flow.
- Result
- Contract changes became reviewable diffs, and audit logs archived to S3 in one consistent structure across the estate.
- Problem
- Services that wrote to the database and published an event did both independently. A crash between the two silently produced lost or phantom events.
- Decision
- Adopt the Transactional Outbox pattern rather than trusting a dual write.
- Implementation
- The business write and the outbox row commit in the same database transaction; a separate relay reads the outbox and publishes downstream.
- Result
- Event emission became at-least-once and recoverable, with the database transaction as the single source of truth.
- Problem
- Hand-migrating 175 services to the new patterns would have consumed the team for the better part of a year.
- Decision
- Automate the mechanical parts of migration behind validation guardrails, and keep humans on the architectural judgment.
- Implementation
- A migration agent using prompt engineering and structured tool calling to analyze, transform, validate, generate and test each service, with every output gated by validation rules and architecture review before merge.
- Result
- Migration became a reviewable pipeline with consistent output, rather than 175 individually negotiated rewrites.
- Kong
- OpenAPI
- OAuth 2.0
- Python
- Java 21 / Spring Boot
- PostgreSQL
- Kubernetes
- Artifactory
- Dynatrace
- S3
Automation · PrudentialMigration agent for service standardizationAn agent-based pipeline that migrates legacy codebases to the new service standard, removing repeated manual migration work.
The problem
Moving legacy services onto the standardized patterns was repetitive but not trivial: each one needed its contract, audit logging, dependencies and response structure reshaped without changing behaviour. Doing that consistently by hand across a large estate is exactly where humans drift and reviews get shallow.
What I built
- An analyze → transform → validate → generate → test pipeline over legacy service source.
- Prompt engineering and structured tool calling so each step returns checkable structured output rather than prose.
- Validation guardrails that reject output failing the standardized contract, audit-log and response rules.
- An architecture review workflow and generated changes are reviewed by engineers before they land.
Engineering decisions
- Problem
- Generated code is only useful if it is consistent and reviewable; free-form output is neither.
- Decision
- Constrain the agent with structured tool calling and treat validation as a hard gate, not a suggestion.
- Implementation
- Each stage emits structured results that are checked against the standard patterns; failures stop the pipeline instead of producing a plausible-looking diff.
- Result
- Output stayed consistent across services and every change arrived in a shape a reviewer could actually reason about.
- Python
- Prompt engineering
- Structured tool calling
- Validation guardrails
Internal product · ModenxService extraction, real-time correctness and cloud costPulling a module out of the monolith, fixing what open SSE connections were costing in load and in data accuracy, and taking $50K+ a year out of the bill.
- labeling cost avoided
- $40K
- annual AWS saved
- $50K+
The problem
Real-time logging and DAU tracking ran over SSE, but connections stayed open for screens the user was no longer looking at. That did two kinds of damage: the same data was delivered more than once, and daily-active-user counts were inflated by screens nobody was watching, so a number the business relied on was quietly wrong. Elsewhere a module still sat inside the monolith, REST responses were shaped for no particular consumer, PostgreSQL absorbed connection churn directly, and cloud spend had never been revisited.
What I built
- A custom batch workflow plugin for an external research team, saving up to $50K in labeling costs.
- An AWS cost initiative that cut spend by $50K+ annually.
- Extraction of a module out of the monolith into a standalone service, with restructured REST APIs and PgBouncer-backed PostgreSQL connection pooling to improve server response time.
- Reworked SSE-based logging and DAU tracking that drops connections for screens no longer in view.
- A data-processing service running scheduled background jobs that crunch customer data at scale for platform-wide analytics and reporting.
Engineering decisions
- Problem
- SSE connections stayed open for screens no longer in view, so the same data was delivered twice and DAU counts were inflated by screens nobody was watching.
- Decision
- Treat visibility as the signal for whether a stream should exist, rather than leaving teardown to the client.
- Implementation
- Reworked SSE-based logging and DAU tracking to drop connections for screens out of view, so a stream exists only while someone is actually looking at it.
- Result
- Duplicate data delivery stopped and DAU counts corrected. The metric started describing real usage.
- Problem
- A module still lived inside the monolith, and short-lived connections hit PostgreSQL directly so connection churn became database work.
- Decision
- Extract the module into a standalone service and pool connections in front of the database rather than tuning each client separately.
- Implementation
- The module moved out behind restructured REST APIs, with PgBouncer as the pooling layer between services and PostgreSQL.
- Result
- Server response time improved and connection handling moved out of the database's critical path.
- Problem
- Customer-data crunching for analytics and reporting competed with work users were waiting on.
- Decision
- Give non-interactive work its own service and its own schedule.
- Implementation
- A data-processing service running scheduled background jobs over customer data at scale, feeding platform-wide analytics and reporting.
- Result
- Reporting scaled on its own terms instead of borrowing capacity from the request path.
- Python
- SSE
- PostgreSQL
- PgBouncer
- AWS
- REST
