Open to senior backend roles

Backend systems for credit risk, built to hold up under scrutiny.

Senior Backend Engineer — 10 years designing and shipping Java & Spring Boot systems for enterprise and financial platforms, from API to architecture.

01

About

I'm a backend engineer with 10 years of experience building reliable systems for enterprise and financial applications. My core stack is Java and Spring Boot, with hands-on experience in REST APIs, backend development, system design, and SQL.

At Macquarie, I've worked on credit risk technology where correctness, auditability, and approval workflows are critical. I've also been building hands-on projects around Kafka, event-driven architecture, microservices, and Go to strengthen my experience with modern distributed backend systems.

Beyond writing code, I care about system design — thinking through scalability, performance, security, failure modes, and long-term maintainability. I also enjoy mentoring engineers and have led engineering initiatives such as our GitHub migration and development workflow improvements.

Based in
Gurugram, India
Focus
Backend Engineering & System Design
Core stack
Java · Spring Boot · REST APIs
Domain
Credit Risk & Financial Systems
Education
B.Tech, Computer Science
Open to
Senior / Lead Backend roles
02

Core Skills

The technologies I use to design, build, and operate production backend systems.

Languages

JavaGo

Backend

Spring BootSpring MVCSpring Security REST APIsMicroservicesKafka Event-Driven ArchitectureHibernate

Databases

SQL ServerPostgreSQLOracle DBRedis

Cloud & DevOps

AWSDockerKubernetes CI/CDGitHub ActionsJenkins

Architecture

HLDSystem DesignMicroservices Event-Driven ArchitectureMonolithic Architecture NFRsScalabilityPerformanceSecurity

Tools & Observability

GitSwaggerSplunk GrafanaNew RelicGitHub Copilot

Frontend (Working Knowledge)

React.jsVue.jsHTML/CSS
03

Experience

Assistant Manager Dec 2021 — Present
Macquarie Group, Gurugram
  • Designed HLD and built end-to-end backend for Country Risk Rating, including formula-driven scoring, multi-stage approval workflow, email notifications, and approval/rejection persistence. Full case study ↓
  • Designed and built Counterparty Notes module with REST APIs, attachment handling, and full CRUD operations.
  • Built SQL-backed Customer data retrieval for a new product, aggregating multiple joins for customer overview.
  • Developed MBE Limits discretion calculator to determine approval tiers and identify valid approved workbooks through multi-step validation across five years.
  • Built React.js credit history modal displaying five years of customer credit history through backend APIs.
  • Streamlined data pipeline (Trino → CSV → SQL Server), eliminating manual sourcing and stale-data reprocessing. Full case study ↓
  • Led GitHub migration, established development/PR practices, mentored developers, and conducted code reviews.
Stack — Java, Spring Boot, REST APIs, SQL Server, AWS, Docker, Splunk, GitHub Copilot, React.js
Consultant Sep 2019 — Dec 2021
Genpact, Noida
  • Owned support and enhancement of enterprise Java web applications — triaging issues from ticketing systems, tracing failures from logs back to root cause in code, and resolving them within SLA.
  • Managed production incident response end-to-end: system outages, job failures, data defects, and end-user issues — including creating, scheduling, and monitoring jobs.
  • Built a new role-management screen with stored-procedure-backed persistence that eliminated a manual process, saving an estimated 500+ person-hours annually.
  • Extended multiple existing web pages with new fields end-to-end — UI, SQL queries, and upload/download file validation — to support evolving business requirements.
Stack — Java, Spring, JBoss, Oracle DB, Jenkins, Docker, AWS, ServiceNow, New Relic, Coverity, CheckMarx, log4j, Apache POI
Senior Software Engineer Oct 2018 — Aug 2019
Diverse Lynx (TCS), Noida
  • Built an IP allocation system with multi-format search (partial IP, IP with netmask, exact match), cross-tool lookups, and a background sync process keeping allocation data current every 5 minutes.
  • Migrated legacy AngularJS interfaces to Vue.js and improved query performance by replacing multi-table joins with a JSON-typed database field for one high-traffic page.
  • Built admin tooling — drag-and-drop ordering, filter groups, sortable search results, and Excel export — backed by REST services consumed via Axios.
Stack — PHP, Zend Framework, MySQL, SQL Server, Oracle, Bootstrap, AngularJS, Vue.js, Axios, SVN
Software Developer Jul 2018 — Oct 2018
Amdocs, Gurugram
  • Developed change requests for Number Portability and fixed production defects and hotfixes in customer order systems, using Amdocs' SOM and MEC platforms in the telecom domain.
Stack — Java, Oracle DB, On-Premise Servers
Software Engineer Jul 2016 — Jul 2018
Narnix Technolabs Pvt. Ltd., New Delhi
  • Built a home monitoring and light-control system following the oneM2M IoT standard, using Java 8, REST APIs, and JSON over an Eclipse OM2M server.
  • Built a full authentication and file-management web application using Java 8, Spring Boot, Spring MVC, Spring Security, Hibernate, and MySQL.
  • Developed the embedded web-server frontend (HTML, Bootstrap, Vue.js) for a C-based embedded system.
  • Rebuilt the company's static website into a dynamic, SEO-optimized site using WordPress, PHP, and MySQL, with uptime alerting configured post-launch.
Stack — Java 8, Spring Boot, Spring MVC, Spring Security, Hibernate, MySQL, REST APIs, WordPress, PHP, Vue.js, C
B.Tech, Computer Science & Engineering
Jaypee University of Engineering & Technology, Guna, M.P.
2012 — 2016
04

Case Studies

Two systems from Macquarie, in more depth than a resume bullet allows.

Backend · Workflow Engine

Country Risk Rating: from scorecard to approved rating

The problem. Business users needed a way to assess country-level risk using a structured scorecard — but the calculation logic, the approval chain, and the audit trail all had to be enforced in software, not spreadsheets, so risk decisions stayed consistent and traceable.

What I built. A user fills in several scorecard fields for a country. Some of those fields are calculated automatically from the others using business-defined formulas — so the backend had to model these dependencies correctly and recompute affected fields as inputs changed. Once complete, the system derives a final country rating from the scorecard.

The rating then enters a multi-stage approval workflow: it's submitted with supporting comments, routed for business approval, and on a decision, the database is updated and the system automatically emails the relevant parties — distinct notifications for approval-needed, approved, and rejected outcomes.

Alongside this, I designed and built the Counterparty Notes module with REST APIs, full CRUD operations, and attachment handling, allowing risk users to attach contextual notes and supporting documents directly to a counterparty's record.

Why it mattered. Before this, rating logic and approvals were harder to track consistently. Centralizing the calculation and approval flow in the application reduced manual back-and-forth and gave business stakeholders a clear, auditable record of how every rating was reached and approved.

Data Engineering · Reliability

Rebuilding the legal entity data pipeline

The problem. Legal entity data was received through a daily feed from an upstream transfer system. The process required manual intervention to source and prepare the data for downstream consumption, creating opportunities for data-quality and stale-data issues.

What I built. I streamlined the daily process by sourcing legal entity data from the enterprise data warehouse using the Trino CLI, generating the required CSV output, correcting the data format, and bulk-loading the data into SQL Server using BCP.

Before loading the data, I added a data-quality check comparing row counts between the data warehouse view and the generated CSV to catch discrepancies before they reached downstream systems.

I also added a validation gate before loading the staging table to confirm that the current day's data was available. This prevented the process from reprocessing older data when the latest data was unavailable.

I coordinated with the data team, Legal Entities team, downstream teams, and business stakeholders to resolve decommissioned-field issues and assess their impact across dependent systems.

Why it mattered. The changes removed manual data-sourcing steps, added validation before processing, and reduced the risk of stale or inconsistent data reaching downstream teams.

05

Projects

Personal backend projects exploring patterns I don't always get to use day-to-day — built end-to-end, including the mistakes along the way.

Java · Spring Boot · Kafka

Event-Driven Order Processing System

Three independent Spring Boot microservices communicating asynchronously through Kafka — modeling how an order moves through creation, payment, and notification without any service calling another directly.

View source on GitHub ↗
Order Service POST /orders
publishes
Kafka order-events
consumes
Payment Service processes payment
Kafka payment-events
consumes
Notification Service logs confirmation

Each service owns its own database and has no knowledge of the others — they only know the shape of the events on the Kafka topics they publish to or consume from. The Order Service writes the order to its database, then publishes an OrderCreatedEvent. The Payment Service, listening on that topic, picks it up, simulates a payment, and publishes a PaymentCompletedEvent of its own. The Notification Service consumes that and logs a confirmation — three services, no direct calls between them, fully decoupled.

Real problem I hit: a poison message stuck the consumer in a retry loop

While testing manually, I pushed a plain string onto the order-events topic instead of a valid JSON payload. The Payment Service's consumer tried to deserialize it into an OrderCreatedEvent, failed, and — because Kafka had already committed that the consumer was "at" that offset for its consumer group — kept retrying the same bad message indefinitely on every restart. The fix taught me how Kafka actually tracks read position: offsets are tracked per consumer group, not per message, so the two real options are moving the group to a fresh offset (effectively a new group-id) or deleting and recreating the topic. I went with the consumer-group reset for a clean fix without losing the topic's other test data, and it's the reason I'm comfortable explaining consumer offset behavior in an interview rather than just reciting it.

Design patterns in play

The system follows the producer-consumer pattern at the messaging layer, with each service applying a simple repository pattern over its own database. The overall data flow accepts eventual consistency by design — there's a deliberate small window where an order exists but payment hasn't processed yet, which is the correct tradeoff for this kind of asynchronous pipeline rather than trying to force synchronous consistency across three services.

Stack — Java, Spring Boot, Apache Kafka, PostgreSQL, Docker Compose, REST APIs
Go · PostgreSQL · Redis

Go Backend Platform — Wallet & Transfers

A fintech-style wallet service modeled on Paytm/PhonePe-style money movement — atomic transfers, async audit logging via a Redis queue, and a separate worker process, written to learn Go's concurrency model hands-on.

View source on GitHub ↗
API Service Gin · cmd/server
tx + lock
PostgreSQL wallets · users
LPUSH
Redis transfer_queue (list)
BRPOP
Worker cmd/worker → audit log

The core feature is a POST /wallets/transfer endpoint that moves money between two wallets atomically — both balances update, or neither does. The naive approach (two separate UPDATE statements) breaks under concurrency and crash scenarios: if the process dies between the debit and the credit, money disappears. I implemented it as a single database transaction with row-level locking (SELECT ... FOR UPDATE) on both wallet rows before reading balances or applying updates.

Real problem I hit: lock ordering and a cross-process deadlock

The first version locked the sender's row, then the receiver's row, in whatever order they arrived in the request. Two concurrent transfers in opposite directions (A→B and B→A) could each lock one row and then block waiting for the other — a classic deadlock. The fix was to always lock the two wallet rows in a consistent order regardless of who's sending and who's receiving (lower user ID first), so two concurrent transfers can never form a circular wait.

Separately, when I moved audit logging off the request path into a background worker, I first tried passing events through an in-memory Go channel between the API and worker. That immediately hit fatal error: all goroutines are asleep - deadlock! — because cmd/server and cmd/worker are two separate OS processes with separate memory spaces; a channel only works within a single process. That was a genuinely useful mistake — it's what pushed me to replace the channel with a Redis-backed queue (LPUSH from the API, blocking BRPOP in the worker), which actually works across process boundaries.

Design and testing

The project follows Go's standard cmd/ + internal/ layout, with each domain (user, wallet, audit) split into model, repository, and handler files to keep HTTP concerns out of business logic. I added integration tests against a real Postgres instance covering the success path and the insufficient-balance rejection path, plus health checks for both Postgres and Redis and graceful shutdown handling for the worker process.

Stack — Go, Gin, PostgreSQL, Redis, Docker Compose, REST APIs
06

Recommended

When I managed Archit for a project at Goodyear, I found him to be skilled and dependable. No matter what I asked him to do, he got it done and he did it quickly. I enjoyed working with him and would have him on my team again.
Justin Frazier
Justin Frazier
Consultant & Founder · LinkedIn recommendation ↗
07

Contact

Let's talk about your team's backend — [email protected]