Staff Software Engineer at Visa, Bengaluru

I build payment systems that stay up.

10+ years building backend systems in Java across payments, e-commerce and logistics. Today I work on card payment authentication at 1,000 TPS and 99.999% availability.

Try it: authenticate a card payment

A simplified simulation of the public EMV 3-D Secure flow I work on. Timings are illustrative.

CheckoutMerchant
3DS ServerMerchant side
Directory ServerCard network
ACSCard issuer
  • Pick a risk level and run the payment to see each step.

About

  • Now: Staff Software Engineer, Visa Secure
  • Leading: a team of 4 engineers
  • Before: Porter, Jio Platforms, FirstHive, eMart
  • Based in: Bengaluru, India

I work on the Directory Server for Visa Secure, the part of EMV 3-D Secure that decides how a card payment gets authenticated before it is authorized. It's a system where a few minutes of downtime means real people can't pay, so most of my time goes into reliability, performance and making releases boring.

Before Visa, I scaled Porter's core services to handle 10x load, built fulfilment microservices and a Kafka retry library for Ajio at Jio Platforms, and ran a campaign engine and loyalty platform handling millions of requests at FirstHive.

I enjoy mentoring engineers through design and code reviews, and I'm always happy to talk about distributed systems, payments or growing into a Staff role.

Work

Visa

Release automation for a payments platform

Releases on a 99.999% availability platform were slow and manual. I led a team of 4 to build an internal deployment tool that standardizes every release step and makes rollbacks predictable.

Release effort down 40%.

Porter

Scaling core services 10x

As part of the Tech Scalability pod, I profiled the hot paths, removed bottlenecks and partitioned large PostgreSQL tables that were slowing down critical queries.

10x load handled; query latency down 30%.

Jio Platforms

Kafka retry library

Async messages between fulfilment services were getting lost on transient failures. I introduced Kafka-based messaging and a reusable retry library with backoff and failure handling.

Adopted across 6 services; message reliability up 25%, downtime down 30%.

Side project

Distributed rate limiter on Redis

A token bucket rate limiter that keeps request counts consistent across many app instances by doing the check-and-decrement atomically in Redis. Try the idea below: the bucket holds 5 tokens and refills one per second.

Token bucket
Tokens available: 5 of 5

See my code on GitHub

Case study: retries without the storm

  • Where: Ajio order fulfilment, Jio Platforms
  • My role: designed and built the library, drove adoption
  • Stack: Java, Spring Boot, Kafka
  • Outcome: adopted by 6 services as the team standard

Picking, packing, labelling and printing ran as separate services that talked to each other asynchronously. When a downstream service timed out or returned a 503, messages were either lost or retried in a tight loop that blocked the partition and kept hitting a service that was already struggling. Every team handled failures a little differently.

The goal was one tested way to fail safely, so teams could stop rewriting retry logic and stop losing shipments to transient errors.

Happy path
Fulfilment topicmain traffic
→
Consumeridempotent, keyed by message
→
Done
Temporary failure: timeout, 503
Retry 1short delay
→
Retry 2longer delay
→
Retry 3longest delay
→
Dead-letter topic
Permanent failure: bad data, validation
Skip retries
→
Dead-letter topicalert, fix, replay
Failed messages leave the main topic, so healthy traffic keeps flowing while failures wait their turn.

Key decisions

  • Classify before retrying. Only failures that can succeed later get retried; bad data goes straight to the dead-letter topic.
  • Non-blocking retry topics. A failing message never holds up the rest of its partition.
  • Backoff, jitter and a cap. Delays grow between attempts, spread out across instances, and stop after a fixed number of tries.
  • Idempotent consumers. A message processed twice has the same effect as once.
  • Shipped as a library. Six services share one implementation instead of six slightly different ones.

Trade-offs I'd call out

  • Ordering. Retry topics let a later event for the same order overtake a failed one. Deduplication doesn't fix that; full-state updates need a version check, and dependent changes need later events held behind the failed one.
  • Replay after an outage. Draining the dead-letter topic all at once can knock the recovered service over again, so replay needs to be rate-limited.
  • More moving parts. Extra topics and alerts to own, in exchange for not losing shipments.

Result: adopted across 6 services, message reliability up 25%, downtime down 30%.

Writing

Deep dive

Apache Kafka, from the inside

My notes from studying Kafka internals through the official docs, Confluent courses and production use. The short version: Kafka isn't a message queue, it's a distributed, append-only commit log. Producers write to the end, consumers read from any position at their own pace, and data stays for as long as retention allows.

Why it's fast

  1. Sequential I/O. Writes only ever append to the end of the log, which disks handle far faster than random writes.
  2. OS page cache, not the JVM heap. Hot data is served from memory with no garbage-collection pauses.
  3. Zero-copy. sendfile() moves bytes from page cache to the network card without passing through the application. TLS turns this off, because data has to be encrypted first.
  4. Batching. batch.size and linger.ms turn many small writes into a few large ones.
  5. One binary format end to end. The broker stores what the producer sent and the consumer reads it as is, with no re-serializing.

Trade-offs you choose

Durability ↔ latencyacks=all with min.insync.replicas=2 is safe but slower; acks=1 is fast but can lose data.
Throughput ↔ orderingMore partitions mean more throughput but no global order; one partition keeps strict order but caps throughput.
Availability ↔ consistencyUnclean leader election keeps the topic writable but can lose data; turning it off avoids loss but can make the topic unavailable.
Throughput ↔ latencyA higher linger.ms batches more for throughput; 0 sends immediately.

Scaling rule: consumer parallelism is capped by the partition count, and partitions can be added later but never removed, so size them for target throughput up front.

Read the full article with diagrams →

More posts on LinkedIn →

Experience

    • Build the Directory Server for EMV 3-D Secure, which authenticates and authorizes card-not-present transactions between merchants and issuers.
    • Engineer a mission-critical platform processing 1,000 TPS at 99.999% availability on Java, Spring Boot, Kafka, Redis, gRPC and Kubernetes.
    • Lead a team of 4 engineers; built a deployment tool that cut release effort by 40%.
    • Scaled core backend services to handle 10x the previous load by finding and fixing system bottlenecks.
    • Implemented PostgreSQL table partitioning, cutting query latency by 30%.
    • Led 6 Spring Boot microservices for Ajio fulfilment across B2C, B2B and Grocery, improving shipment management efficiency by 35%.
    • Introduced Kafka and a retry library adopted across 6 services: 25% better message reliability, 30% less downtime.
    • Built the Label Service from scratch, cutting invoice and label processing time by 40%.
    • Raised pack service throughput by 50%; improved incident response time by 40% with centralized monitoring.
    • Star Performer FY 2023-24 (A* rating).
    • Led the campaign module of a customer data platform serving millions of requests; Java concurrency made campaign runs 30% faster.
    • Built WorldSwipe, a loyalty platform for high-volume points accrual and redemption.
    • Integrated payment gateways (Razorpay, Paytm, Stripe) and OAuth 2.0; cut API response times by 50% with Redis caching.
    • Built Java REST services for a CRM and client support-ticket platform on MySQL.
    • Optimized SQL queries for a 30% performance gain; set up JUnit testing and SonarQube.

Toolkit

Languages and frameworks

Java, Kotlin, Spring Boot, Hibernate/JPA, JUnit, Mockito

Distributed systems

Microservices, Kafka, event-driven design, REST, gRPC, caching, rate limiting, circuit breakers

Payments and security

EMV 3-D Secure, payment authentication and authorization, payment gateways, OAuth 2.0

Data

PostgreSQL, MySQL, Oracle, MongoDB, Redis, Elasticsearch

Cloud and delivery

AWS, Docker, Kubernetes, CI/CD, deployment automation

Observability

Prometheus, Grafana, ELK, Datadog

Let's talk

I'm happy to chat about Staff, Lead and Principal backend roles in payments and fintech, or about distributed systems in general.