Prescription Service
Pipeline-Managed Service
This service is deployed and managed by its CI/CD pipeline.
For current deployment status, configurations, and code:
- Repository:
https://repo.local/healthflow/ndp-prescription-service - CI/CD Status: Check pipeline dashboard
- API Docs: See repository
/docs/api
This documentation describes the service's purpose, architecture, and integration patterns.
Overview
The Prescription Service is the core service responsible for creating, managing, and validating electronic prescriptions (e-prescriptions) in Egypt's National Digital Prescription platform.
Purpose
- Create new prescriptions from healthcare providers
- Validate prescriber credentials and authorization
- Check prescription business rules and compliance
- Store prescription data securely
- Provide prescription lookup and status tracking
- Integrate with Patient Registry and HPR Registry
- Publish prescription events to the event bus
Architecture
Key Features
1. Prescription Creation with Clinical Safety
- Prescriber validation via HPR Registry
- Patient identity verification via Patient Registry
- Medication validation via Medicine Directory
- CRITICAL SAFETY CHECKS (blocking validations):
- Drug-allergy checking (via Patient Registry + CDSS)
- Drug-drug interaction checking (via CDSS)
- Drug-condition contraindications (via Patient Registry + CDSS)
- Duplicate therapy detection (same therapeutic class)
- Age-appropriate dosing (pediatric/geriatric)
- Renal dosing adjustments (based on CrCl from Patient Registry)
- Hepatic dosing adjustments (based on liver function)
- Pregnancy/lactation safety (via Patient Registry)
- Insurance eligibility verification (via Insurance Service)
- Prior authorization check (for high-cost/restricted drugs)
- Generate unique prescription ID with FHIR MedicationRequest
- Support multiple prescription items with clinical validation
2. Prescription Validation Layers
Layer 1: Identity & Authorization (Non-Clinical)
- Check prescriber license validity and authorization
- Verify patient identity and insurance eligibility
- Validate facility accreditation
- Check prescriber specialty vs medication type
Layer 2: Clinical Safety (BLOCKING - Cannot Override)
- Drug allergies: MUST NOT prescribe allergens
- Contraindications: Absolute (pregnancy, conditions)
- High-severity drug interactions: Level 1 (contraindicated)
- Age restrictions: Pediatric/geriatric restrictions
Layer 3: Clinical Warnings (Override with Justification)
- Moderate drug interactions: Level 2-3
- Dosing concerns: Above/below recommended
- Duplicate therapy: Same therapeutic class
- Off-label use: Not approved for indication
Layer 4: Advisory (Informational)
- Cost considerations: Lower-cost alternatives
- Generic equivalents available
- Patient assistance programs
- Clinical guidelines recommendations
3. Prescription Management
- Update prescription status
- Cancel/void prescriptions
- Extend prescription validity
- Track prescription lifecycle
- Partial dispensing support
4. Prescription Lookup
- Query by prescription ID
- Search by patient national ID
- Search by prescriber ID
- Filter by date range, status
- Pagination support
API Endpoints
API Documentation
For complete API documentation with request/response examples, see the service repository.
Core Endpoints
POST /api/v1/prescriptions # Create prescription
GET /api/v1/prescriptions/:id # Get prescription by ID
GET /api/v1/prescriptions # Search prescriptions
PATCH /api/v1/prescriptions/:id/status # Update status
DELETE /api/v1/prescriptions/:id # Cancel prescription
GET /api/v1/prescriptions/:id/history # Get audit historyHealth & Monitoring
GET /health/live # Liveness probe
GET /health/ready # Readiness probe
GET /health/startup # Startup probe
GET /metrics # Prometheus metricsData Model
Prescription Entity (FHIR-Compliant)
interface Prescription {
// FHIR Mapping: MedicationRequest resource
id: string; // UUID
fhirResourceId: string; // FHIR resource ID
prescriptionNumber: string; // Human-readable ID (e.g., RX-2026-000001)
status: PrescriptionStatus; // ACTIVE, DISPENSED, PARTIALLY_DISPENSED, CANCELLED, EXPIRED
intent: "order" | "original-order" | "reflex-order";
// Patient Info (Reference to FHIR Patient resource)
patientId: string; // National ID (14 digits)
patientFhirRef: string; // FHIR: Patient/{id}
patientName: string;
patientAge: number;
patientGender: "male" | "female";
patientWeight: number; // kg (for dosing)
patientAllergies: Allergy[]; // Cached for validation
// Prescriber Info (Reference to FHIR Practitioner resource)
prescriberId: string; // HPR License Number
prescriberFhirRef: string; // FHIR: Practitioner/{id}
prescriberName: string;
prescriberSpecialty: string;
prescriberSignature: DigitalSignature; // Required for legal validity
// Facility Info (Reference to FHIR Organization resource)
facilityId: string;
facilityFhirRef: string; // FHIR: Organization/{id}
facilityName: string;
facilityType: "HOSPITAL" | "CLINIC" | "PHARMACY";
// Clinical Context
encounter: {
encounterId: string; // Visit/encounter ID
encounterType: "INPATIENT" | "OUTPATIENT" | "EMERGENCY";
encounterDate: Date;
};
diagnosisCodes: DiagnosisCode[]; // ICD-10 codes
clinicalNotes: string;
indication: string; // Reason for prescription
// Prescription Details
prescribedDate: Date;
validFrom: Date;
validUntil: Date;
validityDays: number; // Category-based (7-180 days)
// Items
items: PrescriptionItem[];
// Clinical Safety Validations
safetyChecks: SafetyValidation[];
clinicalWarnings: ClinicalWarning[];
overrides: ClinicalOverride[]; // When prescriber overrides warnings
// Insurance & Coverage
insurance: {
providerId: string;
memberNumber: string;
eligibilityVerified: boolean;
priorAuthorizationRequired: boolean;
priorAuthorizationNumber: string;
copaymentAmount: number;
coverageStatus: "COVERED" | "NOT_COVERED" | "REQUIRES_PA";
};
// Refills & Renewals
refillsAllowed: number; // 0 for no refills (e.g., antibiotics)
refillsRemaining: number;
renewalHistory: RenewalEvent[];
// Metadata
createdAt: Date;
updatedAt: Date;
createdBy: string;
version: number;
// Audit Trail
auditTrail: AuditEvent[];
// FHIR Extensions
fhirExtensions: any; // Additional FHIR extensions
}
interface PrescriptionItem {
id: string;
itemNumber: number; // Line number
// Medication (FHIR: Medication resource)
medicineCode: string; // National drug code
medicineFhirRef: string; // FHIR: Medication/{id}
medicineName: string;
medicineNameArabic: string;
activeIngredient: string;
strength: string; // e.g., "500mg"
form: string; // Tablet, Capsule, Syrup, Injection
route: string; // Oral, IV, IM, topical, etc.
// Dosing Instructions
dosage: string; // e.g., "1 tablet twice daily"
dosageStructured: {
dose: number;
doseUnit: string; // mg, ml, units
frequency: string; // BID, TID, QID, PRN
frequencyTimes: number; // 2 (for BID)
timing: string[]; // ["morning", "evening"]
route: string;
duration: number; // Days
durationUnit: "days" | "weeks" | "months";
instructions: string; // "Take with food"
instructionsArabic: string;
};
// Quantity & Dispensing
quantityPrescribed: number; // Total prescribed
quantityUnit: string; // tablets, ml, vials
quantityDispensed: number; // Total dispensed so far
quantityRemaining: number; // Calculated: prescribed - dispensed
// Dispensing Rules
allowPartialDispensing: boolean;
maximumDispenses: number; // e.g., 3 separate fills
dispensesCompleted: number;
dispensingEvents: DispenseReference[]; // Links to Dispense Service
// Substitution Rules
substitutionAllowed: boolean;
genericSubstitutionAllowed: boolean;
therapeuticSubstitutionAllowed: boolean;
brandRequired: boolean;
// Status Tracking
status:
| "PENDING"
| "PARTIALLY_DISPENSED"
| "FULLY_DISPENSED"
| "CANCELLED"
| "EXPIRED";
statusReason: string;
// Clinical Validations (for this item)
drugInteractions: DrugInteraction[];
allergies: AllergyCheck[];
contraindications: Contraindication[];
dosingWarnings: DosingWarning[];
// Cost & Coverage
unitPrice: number;
totalPrice: number;
insuranceCoverage: number;
patientCopayment: number;
// Metadata
createdAt: Date;
lastModified: Date;
}
// Supporting Types
interface Allergy {
allergen: string; // Drug name or class
allergenCode: string; // Code
reactionType: "MILD" | "MODERATE" | "SEVERE" | "ANAPHYLAXIS";
reaction: string; // Rash, swelling, anaphylaxis
verificationStatus: "CONFIRMED" | "SUSPECTED" | "REFUTED";
}
interface DiagnosisCode {
code: string; // ICD-10 code
display: string; // Description
isPrimary: boolean;
}
interface SafetyValidation {
checkType:
| "ALLERGY"
| "INTERACTION"
| "CONTRAINDICATION"
| "DOSING"
| "DUPLICATE";
severity: "CRITICAL" | "HIGH" | "MODERATE" | "LOW";
status: "PASSED" | "FAILED" | "WARNING" | "OVERRIDDEN";
message: string;
details: any;
timestamp: Date;
validatedBy: string; // CDSS service
}
interface ClinicalWarning {
warningType: string;
severity: "HIGH" | "MODERATE" | "LOW";
message: string;
recommendation: string;
canOverride: boolean;
requiresJustification: boolean;
}
interface ClinicalOverride {
warningId: string;
overriddenBy: string; // Prescriber ID
justification: string;
timestamp: Date;
acknowledgedRisk: boolean;
}
interface DrugInteraction {
drug1: string;
drug2: string;
interactionType: string; // Pharmacokinetic, Pharmacodynamic
severity: "CONTRAINDICATED" | "MAJOR" | "MODERATE" | "MINOR";
effect: string; // Description of interaction
management: string; // How to manage
source: string; // Database source
}
interface DigitalSignature {
algorithm: string; // RSA, ECDSA
signature: string; // Base64 encoded
certificate: string; // Prescriber certificate
timestamp: Date;
verified: boolean;
}Integration Points
Clinical Decision Support Service (CDSS) - CRITICAL
Purpose: Patient safety through clinical validations
Validation Requests:
POST /api/v1/cdss/validate-prescription
{
patientId: "29001012345678",
patientAge: 45,
patientWeight: 75,
patientGender: "male",
allergies: [{allergen: "Penicillin", severity: "SEVERE"}],
chronicConditions: ["Diabetes", "Hypertension"],
renalFunction: {crCl: 60, stage: "CKD_3"},
hepaticFunction: "NORMAL",
currentMedications: [
{code: "MED001", name: "Metformin 500mg"},
{code: "MED002", name: "Lisinopril 10mg"}
],
proposedMedications: [
{
code: "MED003",
name: "Amoxicillin 500mg",
dose: 500,
frequency: "TID",
duration: 7
}
]
}
Response:
{
overallStatus: "BLOCKED",
safetyChecks: [
{
checkType: "ALLERGY",
severity: "CRITICAL",
status: "FAILED",
message: "Patient has documented severe allergy to Penicillin. Amoxicillin is contraindicated.",
canOverride: false,
alternativeSuggestions: ["Azithromycin", "Levofloxacin"]
},
{
checkType: "RENAL_DOSING",
severity: "HIGH",
status: "WARNING",
message: "Renal impairment (CrCl 60). Consider dose adjustment.",
recommendation: "Reduce dose to 250mg TID or 500mg BID"
}
]
}Patient Registry - Enhanced Clinical Data
- Verify patient identity
- Retrieve clinical data: allergies, chronic conditions, pregnancy status
- Retrieve functional status: renal function (CrCl), hepatic function
- Retrieve current active medications (medication reconciliation)
- Check patient consent for data sharing
- Validate insurance eligibility
HPR Registry - Enhanced Authorization
- Validate prescriber license and status
- Check prescribing authority: controlled substances, specialty restrictions
- Verify facility accreditation and capabilities
- Check prescriber-facility privileges
- Validate prescriber specialty vs medication type
- Check for any restrictions or suspensions
Medicine Directory - Enhanced Drug Data
- Validate medicine codes (national drug codes)
- Get comprehensive drug data: ATC classification, schedules
- Get therapeutic equivalents: generic alternatives
- Get formulary status: UHIS coverage, restrictions
- Check drug availability and pricing
- Get storage requirements and handling instructions
Insurance/Coverage Service - NEW
- Real-time eligibility verification (UHIS)
- Check coverage for specific medications
- Calculate copayment amounts
- Prior authorization checking: high-cost/restricted drugs
- Submit prior authorization requests
- Track approval status
FHIR Server (HAPI FHIR) - NEW
- Store prescription as FHIR MedicationRequest
- Link to FHIR Patient, Practitioner, Organization resources
- Support FHIR search operations
- Enable international interoperability
- Support CDS Hooks for external clinical decision support
Audit Service
- Log all prescription operations with clinical context
- Track all clinical safety validations
- Record clinical override justifications
- Track prescription lifecycle and modifications
- Record access attempts (who viewed patient data)
- Compliance reporting (controlled substances)
- Support forensic investigations
Kafka Events
Published Events:
# Prescription Created
ndp.events.prescription.created:
prescriptionId: uuid
patientId: string
prescriberId: string
timestamp: datetime
# Prescription Cancelled
ndp.events.prescription.cancelled:
prescriptionId: uuid
reason: string
cancelledBy: string
timestamp: datetime
# Prescription Expired
ndp.events.prescription.expired:
prescriptionId: uuid
timestamp: datetimeBusiness Rules
Prescription Validity (Category-Based)
# Controlled Substances (Egyptian Drug Schedules I-IV)
Schedule I & II (Narcotics, Stimulants):
- Maximum 7 days supply
- NO refills allowed
- Requires special prescriber authorization
- Digital signature MANDATORY
Schedule III & IV (Benzodiazepines, some stimulants):
- Maximum 30 days supply
- Up to 3 refills in 90 days
- Digital signature required
# Antibiotics (Antibiotic Stewardship)
Antibiotics:
- Maximum 14 days supply
- NO refills allowed
- Requires documented diagnosis (ICD-10)
- Tracked for resistance monitoring
# Chronic Disease Medications
Chronic Conditions (Diabetes, HTN, etc.):
- Maximum 90 days supply
- Refills allowed for up to 180 days
- Must have documented chronic condition
# Acute Medications
Acute Conditions:
- Maximum 30 days supply
- 1-2 refills allowed
- Standard validity
# Special Cases
Psychiatric Medications:
- Maximum 30 days supply
- Monthly prescriber review required
- Requires specialty authorization
Chemotherapy/Biologics:
- Per-cycle prescribing only
- Requires oncology specialty
- Prior authorization MANDATORYPrescriber Authorization Matrix
General Practitioner:
Can Prescribe:
- Common antibiotics (not fluoroquinolones)
- Non-narcotic analgesics
- Common chronic disease meds
- OTC medications
Cannot Prescribe:
- Schedule I/II controlled substances
- Chemotherapy
- High-risk psychiatric medications
- Specialty biologics
Specialist (e.g., Cardiologist):
Can Prescribe:
- All general practitioner medications
- Specialty medications in their field
- Some Schedule III/IV with justification
Cannot Prescribe:
- Out-of-specialty high-risk medications
- Schedule I/II without special authorization
Psychiatrist/Neurologist:
Can Prescribe:
- Schedule II-IV controlled substances
- Psychiatric medications
- General medications
Additional Requirements:
- Requires patient monitoring
- State prescription monitoring program (PMP) check
Oncologist:
Can Prescribe:
- Chemotherapy
- Biologics
- Supportive care medications
Requirements:
- Prior authorization for high-cost drugs
- Treatment protocol documentationClinical Safety Rules (BLOCKING)
Drug-Allergy Checking:
- MUST check against patient allergy list
- Cross-allergies checked (e.g., Penicillin → Cephalosporins)
- Cannot override severe/anaphylaxis allergies
- Prescriber must acknowledge mild allergies
Drug-Drug Interactions:
Level 1 (Contraindicated):
- BLOCKED - Cannot prescribe
- Example: Warfarin + NSAIDs (bleeding risk)
Level 2 (Major):
- WARNING - Requires justification to override
- Example: Statins + Fibrates (rhabdomyolysis risk)
Level 3 (Moderate):
- ADVISORY - Prescriber alerted but can proceed
- Example: Antacids + Antibiotics (absorption)
Age-Based Restrictions:
Pediatric (<18 years):
- Weight-based dosing REQUIRED
- Age-appropriate formulations
- Contraindicated drugs blocked (e.g., aspirin <12 years)
Geriatric (≥65 years):
- Beers Criteria checking (potentially inappropriate medications)
- Dose adjustments recommended
- Fall risk medications flagged
Renal Function Dosing:
CrCl <60 (CKD Stage 3):
- Automatic dose adjustment recommendations
- Some drugs contraindicated
CrCl <30 (CKD Stage 4):
- Many drugs require significant dose reduction
- Dialysis considerations
CrCl <15 or Dialysis:
- Severely limited drug options
- Specialist consultation recommended
Pregnancy Categories:
Category X (Contraindicated):
- BLOCKED for women of childbearing age
- Requires pregnancy test or confirmation
Category D (Potential Risk):
- WARNING - Requires justification
- Risk vs benefit documentation
Category B/C:
- ADVISORY - Prescriber alertedMedication Limits
# Opioid Prescribing (Egypt Opioid Stewardship)
Opioids:
- Maximum 7 days for acute pain
- Maximum 30 days for chronic pain (specialist only)
- Morphine Equivalent Dose (MED) calculated
- MED >90mg/day requires justification
- Concurrent benzodiazepine BLOCKED
- State PMP check MANDATORY
- Patient agreement/education required
# High-Risk Medication Quantity Limits
Controlled Substances:
- Quantity limits enforced by schedule
- Early refill BLOCKED (must wait 80% of days supply)
- Lost prescription tracking (limit 2 per year)
High-Cost Biologics:
- Prior authorization REQUIRED
- Step therapy requirements (try cheaper options first)
- Quantity aligned with protocol
- Waste minimization
# Duplicate Therapy Prevention
Same Therapeutic Class:
- BLOCKED if already on same drug
- WARNING for same class (e.g., 2 statins)
- Requires justification to override
# Quantity Limits
General Rules:
- Cannot exceed 90 days supply (even for chronic)
- Cannot exceed package sizes without justification
- Controlled substances: Exact quantity only, no "as needed"Patient Safety Checks
Duplicate Prescription Prevention:
- Check for active prescriptions for same drug
- Check for same therapeutic class
- Alert if prescribing similar medication
- Require prescriber to acknowledge
Drug Recalls:
- Check against EDA recall list
- Block recalled medications
- Alert if recently prescribed medication recalled
Formulary Compliance:
- Check UHIS formulary
- Alert if non-formulary (higher copay)
- Suggest formulary alternatives
- Prior authorization for non-formulary
Dosing Validations:
- Maximum daily dose checking
- Frequency validation
- Route appropriateness
- Duration limits by drug classConfiguration
Environment Variables
# Service Configuration
SERVICE_NAME: prescription-service
SERVICE_PORT: 8080
LOG_LEVEL: info
# Database
DATABASE_URL: postgresql://user:pass@postgresql.data-stack:5432/ndp
DATABASE_POOL_SIZE: 20
DATABASE_TIMEOUT: 30s
# Cache
REDIS_URL: redis://redis.data-stack:6379
CACHE_TTL: 300
# Service Discovery
CONSUL_ADDR: consul.discovery-stack:8500
SERVICE_TAGS: ndp,prescription,api,v1
# External Services
PATIENT_REGISTRY_URL: http://patient-registry.service.consul:8080
HPR_REGISTRY_URL: http://hpr-registry.service.consul:8080
MEDICINE_DIRECTORY_URL: http://medicine-directory.service.consul:8080
AUDIT_SERVICE_URL: http://audit-service.service.consul:8080
# Kafka
KAFKA_BROKERS: kafka.data-stack:9092
KAFKA_TOPIC_PREFIX: ndp.events
KAFKA_CONSUMER_GROUP: prescription-service
# Security
VAULT_ADDR: http://vault.discovery-stack:8200
VAULT_ROLE: ndp-app
JWT_SECRET: <from-vault>
API_KEY: <from-vault>
# Business Rules
PRESCRIPTION_DEFAULT_VALIDITY_DAYS: 30
PRESCRIPTION_MAX_VALIDITY_DAYS: 90
CONTROLLED_SUBSTANCE_MAX_DAYS: 30Monitoring & Alerts
Key Metrics
# Business Metrics
prescription_created_total: Counter
prescription_cancelled_total: Counter
prescription_validation_errors_total: Counter
prescription_processing_duration_seconds: Histogram
# Technical Metrics
http_requests_total: Counter
http_request_duration_seconds: Histogram
database_query_duration_seconds: Histogram
cache_hit_rate: Gauge
kafka_publish_errors_total: CounterAlert Rules
# High error rate
- alert: HighPrescriptionErrorRate
expr: rate(prescription_validation_errors_total[5m]) > 0.1
severity: warning
# Service unavailable
- alert: PrescriptionServiceDown
expr: up{job="prescription-service"} == 0
severity: critical
# Database connection issues
- alert: PrescriptionDatabaseSlow
expr: database_query_duration_seconds > 1
severity: warningSecurity
Authentication
- JWT tokens from identity provider
- API key for system-to-system
- mTLS for service mesh
Authorization
- Role-based access control (RBAC)
- Prescribers can only see their prescriptions
- Patients can only see own prescriptions
- Pharmacists can search prescriptions
Data Protection
- Encryption at rest (database level)
- Encryption in transit (TLS)
- Sensitive data redacted in logs
- Audit trail for all access
Compliance
- GDPR compliant data handling
- Egyptian healthcare regulations
- PII data protection
- Right to be forgotten support
Performance Requirements
Estimates
These are target performance benchmarks. Actual performance depends on infrastructure resources and load patterns.
| Metric | Target | Notes |
|---|---|---|
| Request Latency (p95) | < 200ms | Normal operations |
| Request Latency (p99) | < 500ms | Including validation |
| Throughput | 1000 req/s | Per instance |
| Availability | 99.9% | Three 9s |
| Database Queries | < 100ms | p95 |
| Cache Hit Rate | > 80% | For lookups |
Deployment
Pipeline-Managed
Deployment is handled by CI/CD pipeline. Manual deployment will be overwritten.
Resource Requirements
resources:
limits:
cpu: "1"
memory: 1Gi
requests:
cpu: "500m"
memory: 512Mi
replicas: 3 # Minimum for HA
autoscaling:
minReplicas: 3
maxReplicas: 10
targetCPUUtilization: 70Deployment Strategy
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0Troubleshooting
Common Issues
1. Validation Failures
# Check HPR Registry connectivity
curl http://hpr-registry.service.consul:8080/health
# Check Patient Registry
curl http://patient-registry.service.consul:8080/health
# Check Medicine Directory
curl http://medicine-directory.service.consul:8080/health2. Database Connection Issues
# Check database connectivity
kubectl exec -it prescription-service-xxx -- \
psql -h postgresql.data-stack -U ndp_user -d ndp -c "SELECT 1"
# Check connection pool
curl http://prescription-service:8080/metrics | grep db_connections3. Event Publishing Failures
# Check Kafka connectivity
kubectl exec -it prescription-service-xxx -- \
kafka-console-producer --broker-list kafka.data-stack:9092 --topic test
# Check event lag
curl http://prescription-service:8080/metrics | grep kafka_lagDevelopment
Local Setup
# Clone repository
git clone https://repo.local/healthflow/ndp-prescription-service
cd ndp-prescription-service
# Install dependencies
npm install
# Setup local database
docker-compose up -d postgres redis
# Run migrations
npm run migrate
# Start service
npm run devTesting
# Unit tests
npm run test
# Integration tests
npm run test:integration
# E2E tests
npm run test:e2e
# Load tests
npm run test:loadRelated Services
- Dispense Service - Tracks prescription dispensing
- Patient Registry - Patient master data
- HPR Registry - Healthcare provider data
- Medicine Directory - Drug database
- Audit Service - Compliance logging
Support
For issues, questions, or contributions:
- Issues: internal repository issue tracker
- Slack: #prescription-service
- Email: prescription-team@healthflow.eg
- On-call: PagerDuty escalation