Software Engineer building reliable systems for financial infrastructure.
I work on payment processing at i2c — real-time rails, ISO-20022 message handling, distributed batch workloads, caching architecture and database performance. Systems where correctness and availability are not negotiable.
Selected engineering
All case studies →Payment Distribution Engine
30–40 min → 6–8 min per cycle
A credit-card payment distribution cycle taking 30–40 minutes per execution, rebuilt around range-based processing, card-hierarchy grouping and bounded parallelism.
FedNow ISO-20022 Message Handling
3,000+ parameters, specified and validated
Parsing and validation for US Federal Reserve FedNow ISO-20022 messages, plus the parameter specification that made the implementation reviewable.
Payment Hub — Two-Level Cache
Local JCS → Redis → database
A two-level caching architecture that cut database dependency on the hot path while keeping a single, well-defined invalidation story.
Billing Invoice Engine
Master → workers → RAW files
A horizontally scalable master/worker pipeline for generating large billing RAW files, designed so throughput is a function of worker count.
Enterprise Desktop App — Startup and Size
30–40 s → 5–10 s startup, 25–30% smaller
An enterprise jewellery management platform that took over half a minute to open, traced to eager loading and duplicated UI, then rebuilt around lazy loading and shared components.
Engineering decisions
All decisions →Knowing a technology is table stakes. Knowing why a system is built the way it is — and what it cost — is the part that transfers.
- Why a local cache in front of Redis, instead of Redis alone?Because the two layers answer different questions — one removes the network, the other removes the cold start.
- Why Kafka for cache invalidation rather than Redis pub/sub?Ordering per key, replay for instances that were down, and an audit trail of what invalidated when.
- Why group batch work by card hierarchy instead of by arbitrary chunks?Because grouping by hierarchy removes duplicated work; chunking arbitrarily only redistributes it.
- How do you stop a payment being processed twice?An idempotency key enforced by a uniqueness constraint at the point of record, not a check-then-act in application code.
Engineering journal
All writing →- When Parallel Streams Become a Production ProblemparallelStream() is one call away and looks like free concurrency. On I/O-bound work sharing a JVM-wide pool, it is a way to make unrelated code slow.
- Designing a Two-Level Cache with JCS and RedisA local in-process cache in front of Redis buys latency and resilience. It bills you in invalidation. Here is the accounting.
- What AI Coding Agents Still Get Wrong About Distributed SystemsAgents write correct-looking code very fast. The failures I keep seeing are not syntax or API misuse — they are assumptions about time, ordering and retries.