Portrait of Prashanna Ghimire

Backend Engineer

PRASHANNAGHIMIRE

  • Java
  • Spring Boot
  • Distributed Systems

I build backend systems and APIs with Java/Spring Boot, with practical experience across microservices, messaging, databases, containers and networking.

Open to junior backend roles. Itahari, Sunsari, Nepal.

Built
Five Spring Boot services over REST and Kafka
Packaged with
Docker, Kubernetes and GitHub Actions
Background
Networking and Linux labs, BIT 2026

Projects

Each project is a short case study: the problem, how it is built, and why. Open any one for decisions and details.

Featured engineering projects

  1. Banking MicroservicesFive Spring Boot services connected by Kafka events
  2. Payment ServiceRazorpay orders and webhooks, published as Kafka events
  3. ViviCareMulti-tenant clinic platform with role-based access

Distributed backend · Public on GitHub

Banking Microservices

Five Spring Boot services connected by Kafka events

Outcome
A transfer returns after one debit and one event. Fraud checks, the OTP step, crediting and alerts run asynchronously over nine Kafka topics.
My part
Sole author. Designed the service split and event flow, and wrote all five services with their Docker, Kubernetes and CI files.
Key decisions
  • Debit first, compensate on failure
  • Fraud checks off the request path
  • Redis for OTPs and counters
5
Spring Boot services
11
REST endpoints
9
Kafka topics
47
Java files, about 2,000 lines
5
CI workflows
19
Kubernetes manifests

Problem

A money transfer has to move a balance, run fraud checks and alert the customer. Doing all of that in one synchronous request would tie those concerns together.

Solution

Five independently deployable Spring Boot services. A transfer debits the sender synchronously, saves the transaction as PROCESSING and publishes an event. Fraud checks, OTP verification, crediting the receiver and notifications then run asynchronously over Kafka.

Architecture: Services, Kafka topics and data stores

Entry points

  • ClientREST over HTTP
  • RazorpayPayment webhook

REST services

  • AccountPort 8081. Accounts, balances, credit and deduct. Consumes transaction.completed
  • TransactionPort 8082. Transfers, OTP check, compensation
  • PaymentPort 8085. Razorpay orders and webhook

Synchronous calls over OpenFeign: Transaction to Account (deduct, credit) and Fraud Detection to Account (balance).

Kafka

  • Event backboneServices publish and consume these topics
  • transaction.initiated
  • fraud.check.clean
  • verification.required
  • transaction.otp.generated
  • transaction.completed
  • transaction.refunded
  • fraud.detected
  • payment.completed
  • payment.failed

Event-driven services

  • Fraud DetectionPort 8083. Velocity, unusual amount and share-of-balance checks
  • NotificationPort 8084. Consumes six topics. Alerts are logged for now

Data

  • MySQLJPA persistence for accounts, transactions and payments
  • RedisOTPs with a 5-minute expiry, 60-second fraud counters

Trace a transfer

Step through what each service does for one transfer. This follows the code paths as written; it is not a live system.

Transaction status not created
  1. Client to TransactionPOST /api/v1/transaction with sender, receiver and amount.
  • Java 21
  • Spring Boot
  • Kafka
  • Redis
  • MySQL
  • OpenFeign
  • Docker
  • Kubernetes
  • GitHub Actions
Engineering decisions and details

Key engineering decisions

  • Debit first, compensate on failure. The sender is debited synchronously before the fraud decision. If verification fails or the OTP expires, a compensating credit and a transaction.refunded event reverse it. It is a choreographed saga with no central coordinator.
  • Fraud checks run off the request path. The transfer request returns after publishing transaction.initiated. Fraud Detection decides asynchronously: clean transfers complete, suspicious ones go through an OTP step.
  • Thresholds live in configuration. Transactions per minute, the unusual-amount multiplier and the maximum share of balance are application.yaml properties, so rules change without code changes.
  • Services read each other through APIs. Transaction and Fraud Detection get balances from Account through an OpenFeign client instead of reaching into its data.

Why these technologies

Kafka
Asynchronous communication, so fraud checks and notifications do not block a transfer
Redis
Temporary data: OTPs that expire by themselves and per-account counters with a time window
MySQL
Relational, transactional data accessed through JPA
OpenFeign
Declarative synchronous calls where a result is needed immediately
Docker and Kubernetes
Reproducible images per service, with Deployment and Service manifests for each

Implemented features

  • Account creation with generated 12-digit account numbers, account status and daily limits
  • Transfers with a status lifecycle that includes PROCESSING, PENDING_VERIFICATION, COMPLETED and FLAGGED
  • Three fraud checks: velocity, unusual amount against a running average, and share of balance
  • OTP verification for flagged transfers, stored in Redis with a 5-minute expiry
  • Refund path that credits the sender back and publishes an event for notifications
  • Per-service Dockerfile, Kubernetes manifests and a GitHub Actions workflow that builds and pushes the image

Engineering notes

  • Money moves before the fraud decision, so the failure path matters as much as the happy path. That is why the compensation step exists.
  • Redis does two short-lived jobs: OTPs expire on their own, and a counter with a 60-second expiry drives the velocity check.
  • Services never share a codebase. They agree only on topic names and JSON payloads.

Not built yet

  • API gateway and service-to-service authentication. The JWT library is a dependency of the account service but is not wired in.
  • Idempotent consumers and an outbox for publishing events.
  • Refund path not yet exercised end to end: the account service's credit endpoint is still unmapped, so the compensating call from Transaction needs finishing.

API reference

Account, port 8081. Base path /api/v1/account

  • POST/registerCreate an account
  • GET/{accountNumber}Account details
  • GET/{accountNumber}/balanceCurrent balance
  • PUT/{accountNumber}/blockBlock an account
  • PUT/{accountNumber}/deductDeduct from the balance (called by Transaction)

Transaction, port 8082. Base path /api/v1/transaction

  • POST/Start a transfer: sender, receiver, amount, description
  • GET/{transactionId}Transaction status
  • GET/account/{accountNumber}History for an account
  • POST/{transactionId}/verifySubmit the OTP

Where to look in the code

Payments, Spring Boot 4

Payment Service

Razorpay orders and webhooks, published as Kafka events

Outcome
Razorpay payment results arrive by webhook, update the stored status and reach other services as Kafka events.
My part
Sole author of the service, its Dockerfile, Kubernetes manifests and CI workflow.
Key decisions
  • Webhook-driven state
  • Explicit status enum
  • Secrets from env and a Kubernetes Secret
2
REST endpoints
2
Kafka topics published
5
payment statuses
9
Java files, about 370 lines

Problem

Card payments finish outside the system. The customer pays on Razorpay's checkout and the result arrives later, so the rest of the bank services need to learn the outcome without polling.

Solution

The service creates a Razorpay order, stores a Payment record as CREATED and returns the order details for the checkout. Razorpay's webhook then moves the record to COMPLETED or FAILED and publishes payment.completed or payment.failed to Kafka.

Architecture: Order creation, webhook and events

Outside the system

  • ClientOpens Razorpay checkout
  • RazorpayOrders API and webhook

Service

  • PaymentPort 8085. POST /api/v1/payment/create-order and /webhook

State and events

  • MySQLpayments table with a status enum
  • Kafkapayment.completed, payment.failed

Consumer

  • NotificationPayment alerts
  • Java 21
  • Spring Boot 4
  • Kafka
  • MySQL
  • Razorpay
  • Docker
  • Kubernetes
  • GitHub Actions
Engineering decisions and details

Key engineering decisions

  • Payment state is explicit. A PaymentStatus enum (CREATED, PENDING, COMPLETED, FAILED, REFUNDED) is stored as a string, and amounts use BigDecimal with fixed precision.
  • The webhook drives state changes. Only the Razorpay webhook updates the record and triggers the Kafka event, keyed by payment id.
  • Secrets stay out of the repo. Database and Razorpay credentials come from environment variables, and the Kubernetes Deployment loads them from a Secret.

Why these technologies

Kafka
Publishes outcomes so other services react without being called directly
MySQL
Relational storage for payment records
Docker multi-stage build
Maven build stage, slim JRE runtime image

Implemented features

  • Request validation with Bean Validation on the create-order endpoint
  • Actuator health endpoint for probes
  • GitHub Actions workflow that builds the image on push to main and tags it latest and with the commit SHA
  • Kubernetes Deployment and Service manifests

API reference

Payment, port 8085. Base path /api/v1/payment

  • POST/create-orderCreate a Razorpay order and a CREATED payment. Body: accountNumber, amount, description
  • POST/webhookRazorpay callback: payment.captured or payment.failed

Where to look in the code

Multi-tenant SaaS, Node.js backend · In development

ViviCare

Multi-tenant clinic platform with role-based access

Outcome
A multi-tenant clinic backend with role-based access, a prescription lifecycle and a full inventory chain.
My part
Designed the role-based access control, the prescription lifecycle and the inventory chain on the backend.
Key decisions
  • Tenant per clinic
  • Role-based access control
  • Prescription states, not in-place edits

Problem

Clinics need one platform where each clinic's data and staff permissions stay separate from every other clinic's.

Solution

A clinic management platform where each clinic is a separate tenant. On the backend I designed role-based access control, a prescription lifecycle (draft, issued, cancelled) and a full inventory chain from suppliers and purchase orders to goods receipt and batches.

  • Node.js
  • Express
  • MongoDB
  • Mongoose
  • RBAC
  • REST API
  • Next.js
Engineering decisions and details

Key engineering decisions

  • Tenant per clinic. Every clinic is its own tenant, so access and data are scoped per clinic.
  • Role-based access control. Permissions are tied to roles, so what a user can do depends on their role within their clinic.
  • Prescriptions as a lifecycle. Prescriptions move through draft, issued and cancelled states instead of being edited in place.
  • Inventory as a chain. Stock flows from suppliers through purchase orders and goods receipt into batches.

Why these technologies

MongoDB
Document model for tenant-scoped clinical and inventory records
Express
Thin REST layer over the domain logic

Implemented features

  • Multi-tenant clinic model
  • Role-based access control
  • Prescription lifecycle: draft, issued, cancelled
  • Inventory: suppliers, purchase orders, goods receipt, batches

About

I started in networks and moved up the stack into backend engineering.

The first stage was TCP/IP, subnetting, routing and Linux servers, practised in Packet Tracer and Wireshark labs. That is why I look at what happens between services as well as inside them.

Backend work came next: a news platform API during an internship, then a clinic management system in Node.js, Express and MongoDB. I moved to Java and Spring Boot to build services that depend on each other, and built a five-service banking system to learn how. It uses Kafka for events, Redis for short-lived state, and ships with Docker and Kubernetes manifests.

I am now focused on the parts that make services dependable: failure handling, deployment and observability.

Networking

Hands-on lab work, not professional network engineering. It shapes how I debug and deploy backend services.

Small office LAN

Switches and routers with IP planning and DHCP for 10+ hosts, router access lists and end-to-end testing.

  • Switching
  • DHCP
  • ACLs

ISP-style topologies

Multi-router Packet Tracer labs with WAN links, static routes, inter-VLAN routing, NAT/PAT, DNS and DHCP.

  • VLAN
  • Static routing
  • OSPF basics
  • NAT/PAT
  • DNS

Traffic analysis

Wireshark captures of DNS, TCP handshakes, ARP and HTTP, used to diagnose duplicate IPs and DNS failures.

  • Wireshark
  • TCP/IP

Linux server practice

Static IPs and routing on Ubuntu, SSH access, ufw firewall rules and service monitoring.

  • Ubuntu
  • CentOS
  • SSH
  • ufw
  • systemctl
  • netplan

Skills

Backend

  • JavaBanking services
  • Spring BootBanking services, Payment
  • Node.js and ExpressViviCare, news platform internship
  • REST APIsAll projects

Data

  • MySQLBanking services via JPA
  • MongoDBViviCare via Mongoose
  • RedisOTP expiry, fraud counters

Distributed systems

  • KafkaNine topics across five services
  • MicroservicesBanking services

DevOps

  • DockerDockerfile per service
  • KubernetesDeployment and Service manifests
  • CI/CDGitHub Actions image builds
  • Linux and GitUbuntu, CentOS labs

Networking

  • TCP/IP, DNS, DHCPLabs
  • Routing, switching, VLAN, NAT/PATPacket Tracer labs
  • WiresharkTraffic analysis lab

Experience

Software Developer

2 months

Vividify Solution Pvt. Ltd., Jawalakhel, Lalitpur

  • Worked on a Clinic Management System that is still in active development and not yet launched.
  • Delivered assigned features and fixes in a team, using Git-based collaboration and debugging.
  • This work moved me fully toward backend development.

Backend Developer Intern

3 months

Avyanta Tech Pvt. Ltd., Nepal

  • Built backend REST APIs for a news reporting platform, covering the server-side logic behind news content and reports.
  • Worked with databases and tested API endpoints with Postman.
  • Used Git for version control and collaborated with the team on day-to-day tasks.

Education

Bachelor of Information Technology

May 2021 to March 2026

Mahendra Morang Aadarsha Multiple Campus, Biratnagar

Computer networks, network security, operating systems, database systems, web technologies

Higher Secondary, Science

May 2018 to October 2020

Janasahayog Secondary School, Kathmandu

Let's build

Open to backend engineering opportunities involving Java, Spring Boot and distributed systems.

prashannaghimire29@gmail.com

Itahari, Sunsari, Nepal