Event-driven prescription orchestration engine transforming FHIR R5 to NCPDP SCRIPT v2023011 at 5,000+ TPS with DEA EPCS compliance
RxFlow (go-oec) is a high-performance prescription processing platform designed for healthcare interoperability. It bridges modern EHR systems using HL7 FHIR R5 with pharmacy networks via NCPDP SCRIPT v2023011, implementing event sourcing patterns for complete DEA audit compliance.
| Aspect | Status |
|---|---|
| Maturity | Pre-Alpha / Development |
| Core Engine | Implemented |
| FHIR R5 Models | Complete |
| NCPDP SCRIPT v2023011 | Complete |
| Event Sourcing | Complete |
| Distributed Patterns | Complete |
| API Layer | Implemented |
| Security/EPCS | Stub Implementation |
| Production Ready | No |
- FHIR R5 MedicationRequest ingestion via REST API
- NCPDP SCRIPT v2023011 NewRx message generation
- Bidirectional FHIR-to-SCRIPT transformation
- Event-sourced prescription aggregate with TimescaleDB
- Transactional outbox pattern for reliable messaging
- Idempotency inbox for exactly-once processing
- Circuit breaker pattern for pharmacy routing
- Worker pool for concurrent processing
- OpenTelemetry tracing and Prometheus metrics
- Docker Compose development environment
- DEA EPCS two-factor authentication
- Digital signature infrastructure (PKI)
- Surescripts production integration
- State Prescription Monitoring Program (PMP) integration
- Drug-drug interaction checking
- Post-quantum cryptography (FIPS 203/204)
RxFlow Architecture
+------------------+ +------------------+ +------------------+
| EHR System | | Ingestion API | | Redpanda |
| (FHIR R5 JSON) +---->+ /api/v1/... +---->+ (Kafka Topics) |
+------------------+ +--------+---------+ +--------+---------+
| |
v v
+------------------+ +------------------+
| PostgreSQL | | Routing Service |
| + TimescaleDB |<----+ + Worker Pool |
| + pgvector | | + Circuit Break |
+------------------+ +--------+---------+
^ |
| v
+------------------+ +------------------+
| Outbox Relay | | Pharmacy |
| (Transactional) | | (NCPDP SCRIPT) |
+------------------+ +------------------+
| Pattern | Purpose |
|---|---|
| Event Sourcing | Immutable audit trail for DEA compliance |
| CQRS | Separate read/write models for performance |
| Transactional Outbox | Atomic DB + message queue writes |
| Idempotency Inbox | Exactly-once message processing |
| Circuit Breaker | Prevent cascade failures to pharmacies |
| Worker Pool | Bounded concurrency for throughput control |
| Component | Technology | Purpose |
|---|---|---|
| Language | Go 1.23+ | High-performance, type-safe |
| Message Broker | Redpanda | Kafka-compatible, low-latency |
| Database | PostgreSQL 16 | ACID compliance, JSON support |
| Time-Series | TimescaleDB | Event compression, retention |
| Embeddings | pgvector | AI-powered drug matching |
| HTTP Router | chi | Lightweight, composable |
| Kafka Client | franz-go | High-throughput batching |
| Tracing | OpenTelemetry + Jaeger | Distributed observability |
| Metrics | Prometheus + Grafana | Performance monitoring |
- Go 1.23+
- Docker & Docker Compose
- Make
git clone https://github.com/yourusername/go-oec.git
cd go-oec# Start Redpanda, PostgreSQL, Jaeger, Prometheus, Grafana
make docker-up
# Run database migrations
make migrate-up# Build all services
make build
# Run the ingestion API
./bin/ingestion-api
# In another terminal, run the outbox relay
./bin/outbox-relay
# In another terminal, run the routing service
./bin/routing-service# Create a prescription
curl -X POST http://localhost:8080/api/v1/prescriptions \
-H "Content-Type: application/json" \
-H "X-API-Key: your-api-key" \
-d @test/fixtures/medication_request_lisinopril.jsonPOST /api/v1/prescriptions
Content-Type: application/json
X-API-Key: <api-key>Request Body:
{
"medication_request": { /* FHIR R5 MedicationRequest */ },
"patient": { /* FHIR R5 Patient */ },
"practitioner": { /* FHIR R5 Practitioner */ },
"pharmacy": { /* FHIR R5 Organization */ }
}Response:
{
"id": "uuid",
"status": "pending",
"idempotency_key": "sha256-hash",
"is_controlled": false,
"created_at": "2026-02-25T10:00:00Z"
}GET /api/v1/prescriptions/{id}
X-API-Key: <api-key>GET /api/v1/prescriptions/{id}/events
X-API-Key: <api-key>POST /api/v1/prescriptions/{id}/route
X-API-Key: <api-key>go-oec/
├── cmd/ # Service entry points
│ ├── ingestion-api/ # HTTP API service
│ ├── outbox-relay/ # Outbox pattern processor
│ └── routing-service/ # Pharmacy routing consumer
├── internal/
│ ├── api/ # HTTP handlers and middleware
│ ├── domain/prescription/ # Event-sourced aggregate
│ ├── fhir/r5/ # FHIR R5 data models
│ ├── infrastructure/
│ │ ├── postgres/ # PostgreSQL repositories
│ │ └── redpanda/ # Kafka producer/consumer
│ ├── ncpdp/
│ │ ├── mapper/ # FHIR <-> SCRIPT transformation
│ │ └── script2023011/ # NCPDP SCRIPT v2023011 types
│ └── observability/ # Tracing and metrics
├── pkg/
│ ├── circuitbreaker/ # Circuit breaker pattern
│ ├── idempotency/ # Inbox pattern
│ └── workerpool/ # Bounded worker pool
├── deploy/docker/ # Docker Compose environment
├── migrations/ # PostgreSQL migrations
└── test/fixtures/ # Test data (FHIR JSON)
| Topic | Purpose |
|---|---|
prescription.events |
Domain events (event sourcing) |
prescription.commands |
Command messages |
routing.requests |
Pharmacy routing requests |
routing.responses |
Pharmacy responses |
audit.trail |
DEA audit events |
ncpdp.outbound |
SCRIPT messages to pharmacies |
ncpdp.inbound |
SCRIPT responses from pharmacies |
dead.letter |
Failed message handling |
| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP server port |
DATABASE_URL |
postgres://... |
PostgreSQL connection |
REDPANDA_BROKERS |
localhost:9092 |
Kafka brokers |
OTEL_ENDPOINT |
localhost:4317 |
OpenTelemetry collector |
LOG_LEVEL |
info |
Logging verbosity |
API_KEYS |
- | Comma-separated API keys |
- Go module setup and Makefile
- Docker Compose infrastructure
- Database migrations with TimescaleDB
- FHIR R5 data models
- NCPDP SCRIPT v2023011 structures
- Event-sourced prescription aggregate
- FHIR-to-SCRIPT mapper
- Idempotency key generation
- Transactional outbox pattern
- Idempotency inbox pattern
- Redpanda producer/consumer
- Worker pool implementation
- Circuit breaker pattern
- Routing service
- Pharmacy response handling
- Structured Sig mapping
- NPI/DEA validation
- Drug database integration
- DEA EPCS two-factor auth
- Digital signature (PKI)
- Patient hash salting
- Field-level encryption
- Post-quantum cryptography
- Surescripts integration
- PMP integration
- Performance optimization
- Load testing (5,000 TPS)
- Security audit
| Metric | Target | Current |
|---|---|---|
| Throughput | 5,000 TPS | Not tested |
| Latency (p99) | < 100ms | Not tested |
| Availability | 99.99% | N/A |
| Event Retention | 7 years | Configured |
// Producer (franz-go)
BatchMaxBytes: 16 * 1024 * 1024, // 16MB batches
Linger: 50 * time.Millisecond,
MaxBufferedRecords: 1_000_000,
// Worker Pool
Workers: 100,
QueueSize: 10_000,
MaxRetries: 3,http://localhost:16686
http://localhost:9090
http://localhost:3000
http://localhost:8081
# Run unit tests
make test
# Run integration tests
make test-integration
# Run with coverage
make test-coverageWe welcome contributions! Please see our contributing guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Go idioms and conventions
- Maintain test coverage above 80%
- Document public APIs
- Use meaningful commit messages
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- HL7 FHIR - Healthcare interoperability standard
- NCPDP SCRIPT - E-prescribing standard
- Redpanda - Kafka-compatible streaming
- TimescaleDB - Time-series database
- franz-go - High-performance Kafka client
For questions or support, please open an issue on GitHub.
Disclaimer: This software is provided for development and demonstration purposes. It is not certified for production use in healthcare settings. Proper regulatory compliance, security audits, and certifications are required before processing real patient data.