Skip to content

Microservices Architecture

Overview

VitalBridge is built as a collection of independently deployable microservices.

Each service owns a specific business domain, its database, business rules, APIs, and event contracts.

This architecture enables:

  • Independent development
  • Independent deployments
  • Horizontal scalability
  • Clear ownership boundaries
  • Fault isolation
  • Event-driven integration

The platform follows a strict database-per-service model where each service exclusively owns its data.


Architectural Principles

Domain Ownership

Each business capability belongs to exactly one service.

Examples:

Domain Owning Service
Tenant Registry Tenant Registry Service
Identity Identity Service
Provider Profiles Doctor Service
Patient Profiles Patient Service
Scheduling Doctor Schedule Service
Appointments Appointment Service
Video Sessions Video Session Service

No service may directly modify data owned by another service.


Database Per Service

Every service owns its own PostgreSQL database.

flowchart TB

    DOC["Doctor Service"]
    PAT["Patient Service"]
    APPT["Appointment Service"]

    DOC_DB[("Doctor DB")]
    PAT_DB[("Patient DB")]
    APPT_DB[("Appointment DB")]

    DOC --> DOC_DB
    PAT --> PAT_DB
    APPT --> APPT_DB
Hold "Alt" / "Option" to enable pan & zoom

Benefits:

  • Independent schema evolution
  • Service autonomy
  • Strong ownership boundaries
  • Reduced coupling

Event-Driven Communication

Services communicate through Kafka events.

Instead of:

flowchart LR

    SERVICE_A["Service A"]

    DDA["Direct Database Access"]

    SERVICE_B["Service B"]

    SERVICE_A --> DDA
    DDA --> SERVICE_B
Hold "Alt" / "Option" to enable pan & zoom
VitalBridge uses:
flowchart LR

    PRODUCER["Producer Service"]

    OUTBOX["Transactional Outbox"]

    KAFKA["Apache Kafka"]

    CONSUMER["Consumer Service"]

    PRODUCER --> OUTBOX
    OUTBOX --> KAFKA
    KAFKA --> CONSUMER
Hold "Alt" / "Option" to enable pan & zoom

This allows services to remain independent while maintaining eventual consistency.


CQRS

VitalBridge separates:

  • Commands (write operations)
  • Queries (read operations)

Commands:

  • Create Tenant
  • Add Provider
  • Add Patient
  • Create Appointment
  • Cancel Appointment

Queries:

  • Get Tenant Details
  • List Providers
  • List Patients
  • View Availability
  • View Appointments

Commands modify state.

Queries never modify state.

flowchart LR

    USER["Client"]

    COMMAND["Command API"]

    QUERY["Query API"]

    WRITE_DB[("Write Model")]
    READ_DB[("Read Model")]

    USER --> COMMAND
    USER --> QUERY

    COMMAND --> WRITE_DB
    QUERY --> READ_DB
Hold "Alt" / "Option" to enable pan & zoom

Transactional Outbox

All services implement the Transactional Outbox pattern. Business data and event records are written atomically within the same database transaction.

For example:

flowchart LR

    CMD["Create Appointment"]

    TX["Database Transaction"]

    DATA["Appointment Record"]

    OUTBOX["Outbox Event"]

    PUBLISHER["Outbox Publisher"]

    KAFKA["Apache Kafka"]

    CMD --> TX

    TX --> DATA
    TX --> OUTBOX

    OUTBOX --> PUBLISHER

    PUBLISHER --> KAFKA
Hold "Alt" / "Option" to enable pan & zoom

This guarantees reliable event delivery without distributed transactions.


Service Landscape

The VitalBridge platform currently consists of the following services.

Identity & Access

Identity Service

Responsible for:

  • User provisioning
  • Identity synchronization
  • Role assignment
  • User profile normalization

Database:

  • Identity DB

Tenant Management

Tenant Registry Service

Responsible for:

  • Tenant onboarding
  • Tenant lifecycle management
  • Tenant configuration

Database:

  • Tenant Registry DB

Super Admin Service

Responsible for:

  • Platform administration
  • Tenant oversight
  • Operational controls

Database:

  • Super Admin DB

Admin Service

Responsible for:

  • Tenant administrators
  • Organization management
  • Administrative workflows

Database:

  • Admin DB

Clinical Operations

Doctor Service

Responsible for:

  • Provider profiles
  • Credentials
  • Taxonomy information
  • Professional metadata

Database:

  • Doctor DB

Patient Service

Responsible for:

  • Patient profiles
  • Demographic information
  • Patient-related workflows

Database:

  • Patient DB

Doctor Schedule Service

Responsible for:

  • Weekly availability templates
  • Schedule overrides
  • Leave requests
  • Effective availability calculations
  • Appointment blocking

Database:

  • Doctor Schedule DB

Appointment Service

Responsible for:

  • Appointment booking
  • Rescheduling
  • Cancellation
  • Appointment lifecycle management

Database:

  • Appointment DB

Telehealth

Video Session Service

Responsible for:

  • Video session creation
  • Join token generation
  • Meeting validation
  • Video provider integration

Database:

  • Video Session DB

Platform Services

Communication Engine Service

Responsible for:

  • Email delivery
  • SMS delivery
  • Notification orchestration

Database:

  • Communication DB

Audit Log Service

Responsible for:

  • Audit event storage
  • Compliance tracking
  • Operational auditing

Database:

  • Audit Log DB

Analytics Service

Responsible for:

  • Reporting
  • Aggregation
  • Analytics workloads

Database:

  • Analytics DB

Service Communication

The following diagram illustrates how services communicate.

flowchart LR

    SERVICE_A["Service A"]

    KAFKA["Apache Kafka"]

    SERVICE_B["Service B"]

    SERVICE_A -->|"Publish Event"| KAFKA

    KAFKA -->|"Consume Event"| SERVICE_B
Hold "Alt" / "Option" to enable pan & zoom

Services never communicate through shared databases.

All state changes are propagated through events.


Service Boundaries

VitalBridge enforces strict ownership boundaries.

A service may:

  • Read and write its own database
  • Publish events
  • Consume events
  • Expose APIs

A service may not:

  • Write to another service's database
  • Share database schemas
  • Depend on internal implementation details of another service

These boundaries allow services to evolve independently while maintaining platform consistency.