Berlin // Backend & Integration // Open to roles

Bhavyashree
Prakash

I build the layer between systems that were never designed to talk to each other.

Production REST APIs and integrations in Node.js, TypeScript and Java. Most of what I know about reliable systems I learned carrying a pager for the ones I wrote.

Network routing — live Click a node to fail it. Traffic reroutes.
01

What I actually do

I spent 1.8 years at Cognizant as a MuleSoft developer on an enterprise insurance client's integration platform, building API-led services in Mule 4: payment gateway integration, settlement and payment-status tracking, APIs for party creation, sanction screening and notifications, and moving legacy document handling off a file share. The interesting failures happen after launch, at the boundary between two services where neither team owns the problem.

The piece I would point at is the reconciliation — comparing gateway transactions against internal financial records end to end, because a payment integration that is merely up is not the same as one whose books agree. The rest was the unglamorous work that decides whether an integration lasts: two-way SSL between services, a caching policy in the process API for calls that did not need to reach the backend every time, and pulling logic out of the system APIs into the process layer so a change had one place to live instead of several.

Since finishing an MSc in Computer Science in Berlin I have kept building in the open, most recently an API-led integration platform over German electricity-market data that runs unattended and records every upstream failure it meets. What I care about is reliability of a particular kind: systems that are debuggable, not just correct. The failures worth designing for are the ones that return a perfectly well-formed answer with the wrong numbers in it — nothing throws, every assertion passes, and the only way to catch it is to have built something you can interrogate afterwards. Anything can pass its tests on a good day.

02

Work

GridPilot

Deployed & scheduling

Python · FastAPI · LightGBM · pandas · PostgreSQL · Prometheus · Grafana · Docker · Caddy

A scheduler for work that can wait. A job arrives with a deadline — a backup, a report, a model retrain — and GridPilot places it in the hours when German electricity is cheapest or cleanest, using published day-ahead prices where they exist and its own forecasts of price and grid carbon intensity where they don't. Every plan can explain itself: the curve it saw, which hours were real data and which were forecasts, and what running immediately would have cost.

The honest result came first. Replaying a year day by day, with every forecast limited to what was known at 10:00 the day before, “always start at 11:00” beat every forecasting baseline on carbon. Carbon in Germany follows the wind, and wind does not repeat weekly. A LightGBM model with weather inputs finally beat the rule — but only after making sure those inputs were weather forecasts made two days earlier, not the weather that actually happened. With real weather the model quietly knows tomorrow's wind, and the backtest looks wonderful and means nothing.

Carbon window regret vs the 11:00 rule12.4 → 7.0 g/kWh
Carbon forecast error97 → 46 g/kWh
One-year saving vs nightly cron, share of perfect foresight−50% cost, −42% CO₂ · 97%

The check worth recording is the one I nearly left out. The feed monitor opened an incident when an upstream failed several runs in a row, and it caught a simulated Energy-Charts outage cleanly. But a stopped ingestor fails nothing: no error, no failed run, just data quietly going stale while every check passes. It now also alerts on silence. The other lesson came from the live system: a price forecast made 38 hours ahead was far too high on the level, yet picked exactly the right cheapest window, because a scheduler needs the shape of the day, not the number.

energy-hub

Deployed & polling

MuleSoft 4.6 CE · RAML · DataWeave · MUnit · PostgreSQL · Docker · Caddy

An API-led integration layer over German day-ahead electricity prices. Four Mule applications across system, process and experience layers, polling two independent upstreams on a schedule and serving a household view of when power is cheap. It has been running unattended on a free-tier ARM instance since the start of October, and records every poll attempt it makes, successful or not.

Both upstreams publish the same EPEX auction, which makes them a check on each other: an hourly price has to equal the mean of the four quarter-hours inside it. That started as a way to work out which of ENTSO-E's two auction sequences was the right one, and it now runs as a comparison on every request. The feeds are never merged, though — ENTSO-E is quarter-hourly and aWATTar is hourly, and downsampling throws away the detail where negative-price spikes live while upsampling invents detail that isn't there.

The failure log is the part I would point at. Five bugs on this project returned perfectly well-formed responses with the wrong numbers in them: a flat price curve from a consumed stream, timestamps shifted two hours by a timezone relabel, an entire upstream that silently stopped being polled while the monitoring table went on reporting success. Every structural assertion passed each time. NOTES.md has all of them, including the one where the fix was confidently wrong and a query settled what reasoning could not.

bahnwatch

Deployed & polling

Python · FastAPI · WebSockets · asyncio · NumPy · SQLite · systemd · Caddy

A commute alerter that answers when to leave rather than what is late, running on the official VBB feed for a journey I actually make. Delay magnitude is the wrong trigger: on a single leg a delay costs you at most one headway, because you take the next train. On a connection it either still works, costing nothing, or it does not, costing the full wait for the next service. The cost is a step, not a ramp, and the step is where the whole risk sits — so the alert fires on the shift in leave time, behind hysteresis and a daily cap, because an alerter that cries wolf gets muted and is then worth less than nothing.

The bug worth recording is the leave time itself, which is the entire output. It was computed by subtracting walk, ride, transfer and buffer from the target arrival. Every one of those numbers was right. The answer was twenty minutes wrong, because the arithmetic has no idea that trains leave at times: it returned 21:48, which puts you on the platform for the 22:00 rather than the 21:50, into Friedrichstrasse one minute after the connecting S7 has gone. It now plans backwards through services that exist — the last train on the final leg that still meets the target, then the last train that connects into that one, down to the door.

Most of the rest came from swapping a simulator for the real feed. The planner had been matching departures by line and never by direction, which the simulator could not expose because it gives every line exactly one destination; at the real S Blankenburg the S2 alternates north and south, so half the trains it timed me onto were going the wrong way. Then the first fix was wrong in the opposite direction, because a terminus is not a direction either. A fake data source reproduces the shape of real data and none of its awkwardness, and the README has all five.

Shipment Tracking Aggregator

Deployed & running

TypeScript · NestJS · Docker · Jest · Render

Unifies several external carrier APIs behind one internal contract. Nearly all the engineering in it exists for one reason: the upstreams are unreliable and the service has to be anyway. Circuit breakers so a failing carrier can't take the rest down, retry with exponential backoff and jitter, token-bucket rate limiting to stay inside partner quotas, HMAC-signed webhooks, and schema normalisation at the adapter boundary. 68 tests.

Double-Entry Ledger

PostgreSQL · CI green

PostgreSQL 16 · PL/pgSQL · Docker · GitHub Actions

An accounting ledger where correctness is the database's job. Every entry must balance to zero, posted entries are immutable, and corrections are reversals rather than edits — all enforced by constraint triggers, because an application can always be wrong and an unbalanced entry doesn't crash anything, it just makes every report downstream quietly false. Bitemporal history separates when something happened from when the ledger learned about it, so you can ask what the books said on a past date before a later correction existed.

The part worth reading is the concurrency test. Two simultaneous withdrawals of 60.00 from a balance of 100.00 both pass their own balance check and both commit, leaving the account at −20.00. Neither transaction did anything wrong; the invariant breaks on the interleaving. SELECT … FOR UPDATE doesn't fix it — the constraint spans an aggregate and the offending row doesn't exist yet. The test reproduces the anomaly deterministically and proves SERIALIZABLE prevents it.

Parcel Analytics Warehouse

PostgreSQL · CI green

PostgreSQL 16 · Docker · GitHub Actions · 12.4M rows

A star schema for parcel logistics built at a size where the decisions matter — 2 million shipments and 10.4 million scan events, range-partitioned monthly. Every index justified by a before/after measurement rather than a habit, including one query where indexing changed nothing because partition pruning had already done the work.

Scan history of one parcel1,592 ms → 0.95 ms
One customer's full history271 ms → 13.4 ms
Regional revenue via matview979 ms → 14.5 ms
Carrier SLA breaches — no gain127 ms → 120 ms

GitOps Delivery Pipeline

Python · Kubernetes

FastAPI · Helm · ArgoCD · kind · Prometheus · GitHub Actions

The whole path from commit to running workload on Kubernetes, reproducible on a local cluster. CI's last act is writing the image tag into git; an in-cluster agent reconciles the rest. The application is small on purpose — the delivery path is the subject. 18 tests at 97% coverage.

Feature Flag & A/B Testing Service

TypeScript · React

NestJS · TypeORM · MySQL · Jest · React · Vite

Multi-tenant flag evaluation with percentage rollouts and deterministic bucketing, so the same user always lands in the same variant. Paired with a React and TypeScript operator console for real-time flag management. 114 tests across both, CI enforced on every merge.

03

Experience

2022 — 2024

Programmer Analyst — Backend & Integration

Cognizant Technology Solutions · Bengaluru

Built and maintained 25+ production REST API integrations in Node.js and Java, bridging internal platforms with external partner systems at 99.9% uptime. Implemented OAuth 2.0 flows for partner-facing endpoints, sat with client stakeholders to work out what their process actually was, and carried a pager for everything I shipped.

2024 — 2026

Operations Associate

Amazon Logistics · Werder

Not a software role — taken while completing my MSc full-time. It's why the logistics domain isn't abstract to me: receive, sort and dispatch at volume, and what happens on the floor when a scan doesn't resolve.

2024 — 2026

MSc Computer Science

IU International University of Applied Sciences · Berlin

Thesis on multimodal deep learning for music emotion recognition. Preceded by a BE in Electronics and Electrical Engineering, Bengaluru.

04

Stack

Languages

  • TypeScript / JavaScript
  • Java
  • Python
  • SQL

Backend

  • NestJS · Express · FastAPI
  • MuleSoft 4 · RAML · DataWeave
  • REST API design & versioning
  • Microservices
  • OAuth 2.0 · webhooks
  • Kafka · event-driven

Data

  • PostgreSQL · MySQL
  • Schema design
  • Query optimisation
  • Partitioning
  • DynamoDB

Infrastructure

  • Docker · Kubernetes
  • Helm · ArgoCD
  • GitHub Actions · CI/CD
  • AWS
  • Prometheus · Grafana

Certified

  • MuleSoft Developer L1
  • MuleSoft Integration Associate

Languages spoken

  • English — C1
  • German — B1
  • Hindi — native
05

Get in touch

Open to backend, integration and platform engineering roles. Based in Berlin, happy to relocate within Germany.