Practice management software(PMS): Microservices architecture
This article explains various microservices involved in building a practice management software(PMS). A PMS is used by medical practitioners to manage the daily operations like appointment scheduling to insurance processing and in some cases, to store medical records.
The base architecture
A feature-rich PMS tends to be huge with several modules like insurance module, electronic medical records module, etc. This software is a perfect candidate for a microservices-based architecture.
In a microservice-based architecture, a set of related functionality becomes a specialized service. An application can have tens or even hundreds of loosely coupled services. Such dedicated services tend to be easy to maintain, test, and debug.
Not all is hunky-dory with microservices. They come with their challenges. Developers will have to make the individual services fault-tolerant, think about network latency while deploying and hone distributed tracing skills.
Microservices in a Practice Management Software
Web Application
It contains all the presentation logic and calls other services to serve the needs of the users.
User Management Service
It contains the basic information of the users of the system, such as doctors, nurses, patients, receptionist, etc. It is responsible for authorization and authentication.
Appointments Service
It is a very lightweight service that integrates the doctor's calendar with the software. It communicates with the "Notification Service" to send notifications to the patient/doctor regarding the appointment.
Medical Records
This service contains the patient's medical information in an encrypted format. Only the users that have valid access roles can access these records. It uses the notification service to notify the owner of the medical records whenever someone requests access for them.
Notification Service
This service sends a notification to the users based on the preference. It can send a notification via email, app notification, or iMessage.
Insurance Service
The responsibility of this service is to integrate with different insurance companies to get the insurance-related information/approval.
Payment Service
The responsibility of this service is to integrate with different payment mechanisms such as card payments, PayPal, Apple Pay, etc.
Reporting Service
All the services can publish "events" ( such as AppointmentCreated event ) when a change occurs on an event bus like Apache Kafka, and the reporting service can subscribe to interesting topics and update its local database based on the payload of the event.
Advantages of this architecture
- Integrate with new payment/insurance systems by making changes only to the payment/insurance services and not any other part of the system.
- Separates user information from the actual patient records: This improves the security of the system and makes it easier to control who has access to this sensitive information.
- Stable services such as appointment service need not be required to redeploy due to changes in a different part of the system.
- We can create a different number of replicas of the web application & the other services based on the demand.
- Even if a service is slow (e.g., because of an external API), the rest of the system continues to work well.
- It is easier to onboard a new engineer to work on the system.
Design Considerations
Databases for Microservices
Each service should have and own its data, i.e., database. No service should share a single database with another service. One reason for this is any change in the schema of the database will require us to deploy the other service too. Another idea is to create an anti-pattern of adding the logic of one service into another service.
JSON vs. gRPC
gRPC ( a google version of protocol buffers ) is the preferred way of communication between microservices instead of JSON. Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. They are better than JSON in terms of speed of encoding and decoding, size of the data on the wire, and more. They also make it easy to handle backward compatibility. Here is an article detailing the versioning of gRPC ( protocol buffers ): https://www.beautifulcode.co/blog/88-backward-and-forward-compatibility-protobuf-versioning-serialization.
Event-Driven Architecture for Reporting Service
One main reason to consider for using "Events" for reporting service is to let the system work without any interruptions even if the reporting service is down. Once the reporting service is back online, it can still receive all the events that were emitted and update the database.
Master-Slave Architecture for Reporting Service
If there is a lot of traffic for the reporting service, consider using the Master-Slave architecture for the database. There are two or more replicas of the database. One of the replicas becomes the "Master," and handles all the writes. The rest of the replicas become "slaves" and at regular intervals, update the changes from the "Master" replica.
This architecture helps to increase the throughput of the system by locking the database for writes in only one database (i.e., the "Master"), and all the read operations are performed on the other databases (i.e., the "Slaves").
Important Links
- Microservices related patterns: https://microservices.io/
- Kubernetes for deploying the application in the cloud: https://kubernetes.io/
- Pattern to migrate from Monolith to Microservices architecture: https://dzone.com/articles/monolith-to-microservices-using-the-strangler-patt