
When One Service Fails, the Rest Keep Running: The MediCare Architecture
Healthcare workflows span domains with very different failure tolerances. A payment failure needs careful, non silent handling, while a symptom checker being briefly unavailable is a minor inconvenience. Building this as a single application would mean every domain shares the same deployment cycle and the same blast radius when something breaks, so an outage in telemedicine could end up slowing down or taking down unrelated things like appointment booking or patient records.
Split the backend into eight services by domain rather than by technical layer, Auth, Patient, Doctor, Appointment, Telemedicine, Payment, Notification, and AI Symptom, unified behind a single NGINX gateway that handles routing, compression, rate limiting, and security headers in one place. Appointment booking is treated as a sequence of state transitions rather than one atomic operation, since it touches patient, doctor, and payment data at once, and JWT validation logic is shared across all eight services from a single Auth service rather than reimplemented independently in each one.
A microservices healthcare platform handling patient records, appointment booking, telemedicine, billing, and AI assisted symptom checking, built as eight independent Spring Boot services behind a single NGINX gateway and deployed through Kubernetes.
Table of Contents
Case Study: MediCare, A Microservices Healthcare Platform
Overview
MediCare is a healthcare management platform covering patient records, doctor scheduling, appointment booking, telemedicine, billing, AI assisted symptom checking, and notifications. It is built as eight independent Spring Boot services behind a single NGINX gateway, deployed through Kubernetes, with a React frontend on top. This case study covers the actual engineering decisions behind that design, including the tradeoffs that came with them, rather than treating the architecture as self evidently correct.
The Challenge
Healthcare workflows involve several domains that behave very differently under load and under failure. Booking an appointment, running a live video consultation, processing a payment, and generating an AI symptom summary are not variations of the same problem, they are different problems with different failure tolerances. A payment failure needs to be handled carefully and never silently, while a symptom checker being briefly unavailable is an inconvenience, not a crisis.
Building this as a single application would mean all of these domains share the same deployment cycle, the same runtime, and the same blast radius when something goes wrong. The core challenge was designing a system where an outage or a bug in one domain, for example the telemedicine video layer, could not take down or slow down an unrelated domain, like appointment booking or patient records, while still keeping the system operable by one team without the overhead of managing eight completely different technology stacks.
The Solution
The backend is split into eight services by domain rather than by technical layer, Auth, Patient, Doctor, Appointment, Telemedicine, Payment, Notification, and AI Symptom, each built on the same Spring Boot 3 and Java 17 foundation to keep the runtime consistent while the domains stay isolated. A single NGINX gateway sits in front of all eight services, handling route resolution, GZIP compression, rate limiting, and security headers in one place instead of repeating that logic across every service.
Two of the harder coordination points in the system are appointment booking and authentication. Appointment booking touches patient data, doctor availability, and eventually payment, so it is handled as a sequence of state transitions, requested, confirmed, completed or cancelled, rather than a single atomic operation, which limits how much damage a partial failure can do. Authentication is handled by a dedicated Auth service that issues JWTs, with validation logic shared across the other seven services rather than reimplemented independently in each one, avoiding both a synchronous dependency on Auth for every request and the risk of validation logic drifting out of sync across services over time.
The AI Symptom service wraps its third party AI integration behind its own internal API, so the underlying provider can be changed without that change rippling into any other part of the system.
For deployment, the platform targets Kubernetes through Minikube, with a one click PowerShell setup script that provisions the cluster and required tooling automatically, and a Docker Compose path available for anyone who wants to run the full backend without a Kubernetes cluster. Secrets, including MongoDB URIs, Stripe keys, OpenAI keys, and JWT secrets, are injected through environment variables and Kubernetes secrets rather than committed to the repository, with CI/CD pulling credentials through a Jenkins secret file credential.
Where the Tradeoffs Actually Show Up
This design is not free, and it is worth being specific about the cost rather than only listing the benefits.
Debugging a single user facing request, for example booking an appointment, can mean tracing it across Auth, Patient, Doctor, and Appointment services instead of reading one stack trace in one process. Running the system locally means managing eight separate service processes and MongoDB connections instead of one. Building and pushing eight separate container images on every push to main costs more CI time and registry storage than building one combined image would.
None of these costs are hidden or accidental. They are the direct, expected price of the isolation guarantees the architecture is built to provide, and they only make sense because of what the system is handling. A single clinic booking tool would not justify this complexity. A platform meant to keep patient records, live video, and billing operating independently of each other does.
Key Outcome
The concrete evidence that the domain isolation works as intended is structural rather than a measured metric. The AI Symptom service can have its underlying provider swapped without touching Patient, Doctor, or Appointment code. Telemedicine session handling can fail or scale independently of appointment booking, since the two do not share a deployment or a runtime. And the shared JWT validation approach means all eight services enforce the same authentication contract without each one reimplementing it separately, which removes a class of bug where one service's auth check quietly drifts out of sync with the others.
Honest Limitations
A few things are worth stating plainly rather than glossing over. The system has not been documented here under real, sustained production load, so claims about how it performs under concurrent traffic across all eight services would be speculation rather than something demonstrated. The shared JWT filter logic, while it solves the consistency problem, is also a deliberate point of coupling in an otherwise decoupled system, and any change to that shared logic has to be coordinated carefully across every service that depends on it. Those are the honest boundaries of what this architecture has actually proven versus what it is designed to eventually support.
Takeaway
The value in this system is not that microservices are automatically the right choice. It is that the specific isolation, independent scaling, and centralized security enforcement match what a multi domain healthcare platform genuinely needs, and the operational cost of running eight services was accepted deliberately because of that match, not despite it.


