Patient-Management: A Microservice Stack That Chooses the Right Protocol for the Job

A Java 21 healthcare backend that routes auth through the gateway, hardens billing with gRPC, and pushes analytics through Kafka.

8 min read • View on GitHub • More from Chiru-5

A hospital control room splits one patient intake desk into three distinct channels: a guarded doorway for token checks, a sealed mechanical coupling for billing, and a pneumatic relay for analytics. The scene explains the repo’s central idea that one workflow can use different transports depending on how tightly each dependency must be coupled.
One patient flow, three communication styles. The repo’s design choice is the story.
Key Takeaways

Most patient systems are judged by fields, forms, and screens. This repo is more interesting than that. It turns patient creation into a transport decision: verify at the edge, confirm the hard dependency synchronously, and publish the loose dependency asynchronously.

Patient Management System

Chiru-5, Project Creator/Maintainer · Chiru-5/Patient-Management README

Why This Repo Is Really About Boundaries

The repository reads like a compact reference architecture for a simple rule: not every downstream system deserves the same level of urgency. Some work must finish before the transaction can be called successful. Some work only needs to happen eventually. Patient-Management makes that distinction explicit instead of burying it inside one generic service call.

That is why the stack feels opinionated. REST handles the public edge. gRPC handles the strict internal handshake. Kafka handles the parts of the system that should not hold the user hostage.

The Three-Lane Workflow Behind Patient Creation

The `createPatient` flow is the center of gravity. First the record is persisted locally. Then billing is created synchronously. Then an event is emitted for analytics. One domain action fans out into three coordination modes, and the repo is careful about which one lives where.

The system’s real shape is a routing problem. Each edge carries a different promise.

What the flow is really optimizing for

The gateway decides who gets in. The patient service decides what must be true now. Billing needs an immediate answer, so the system waits for gRPC. Analytics can arrive later, so the system publishes to Kafka and moves on. That is a small architecture decision, but it is the whole thesis of the repo.

TransportRole in this repoCoupling levelWhy it is used hereWhat would break if it were replaced
RESTPublic API at the edgeModerateIt is easy to expose and easy to test from client toolsThe external contract would become less accessible
gRPCBilling handshakeTightThe service needs an immediate, strongly typed confirmationPatient creation would no longer know whether billing succeeded
KafkaAnalytics broadcastLooseThe domain should not wait on downstream consumersA slow analytics service would delay the core workflow
A close-up of a patient record being stamped, passed through a rigid billing aperture, and then released into a separate tube that carries it away to analytics. A guard in the foreground checks a token before the record can move. The image explains the difference between hard and soft dependencies in the same workflow.
The close-up view shows the same rule from the other angle: billing is blocking, analytics is not.

The Gateway Is Not Just a Door

The gateway is doing more than routing requests. It is enforcing trust before the request reaches the business core. Instead of validating tokens locally and hoping every service stays aligned, the filter calls auth-service and asks the system of record to vouch for the request.

// Gateway filter pattern in the repo
// Validates JWTs by calling auth-service before routing
public class JwtValidationGatewayFilterFactory extends AbstractGatewayFilterFactory<Config> {
    // ...
}

That design keeps internal services simpler. They do not all need to know how to verify or re-verify the same token logic. The cost is an extra network hop at the edge, but the payoff is a clearer trust boundary.

Why Billing Uses gRPC and Analytics Uses Kafka

This is the repo’s cleanest comparison. Billing is a hard dependency because the system wants an immediate answer before the transaction is complete. Analytics is a soft dependency because the primary workflow should not stall if downstream reporting is slow or unavailable.

QuestiongRPC for billingKafka for analytics
Does the caller need an immediate answer?YesNo
Should the request block?YesNo
Is the dependency business-critical?YesNot for the user-facing transaction
Would a failure change the user outcome now?YesUsually not

The important lesson is not that gRPC is faster or Kafka is modern. It is that transport follows dependency shape. If the domain cannot proceed without the result, make the call explicit and synchronous. If the domain can proceed without waiting, publish an event and let consumers catch up.

Infrastructure Written in the Same Language

The infrastructure layer keeps the same Java-first opinion. AWS CDK lives beside the services, so the stack is modeled in the same language as the application. That lowers the friction between business logic and deployment logic, which matters when the environment itself is part of the demo.

LocalStack strengthens that idea. The repo does not just describe AWS resources. It rehearses them locally. That makes the project feel closer to a platform blueprint than a classroom sample.

What This Repo Is, and What It Is Not

Patient-Management is a strong reference architecture. It is not a finished healthcare platform. Some service behavior is intentionally skeletal, including the kind of hardcoded responses you would expect in a learning repo rather than a regulated production system.

That is not a flaw in the article’s subject. It is the point. The code is trying to teach a pattern, and the pattern is crisp: choose the protocol that matches the boundary.