| name | openevidence-migration-deep-dive |
| description | Execute complex OpenEvidence migrations including EHR integration, data migration, and system transitions.
Use when migrating from legacy clinical decision support systems, integrating with new EHRs,
or performing major platform transitions.
Trigger with phrases like "openevidence migration", "ehr integration",
"migrate to openevidence", "clinical ai migration", "legacy cds migration".
|
| allowed-tools | Read, Write, Edit, Bash(npm:*), Grep |
| version | 1.0.0 |
| license | MIT |
| author | Jeremy Longshore <jeremy@intentsolutions.io> |
OpenEvidence Migration Deep Dive
Overview
Execute complex migrations including EHR integration, legacy system transitions, and multi-site deployments for OpenEvidence clinical AI.
Prerequisites
- Understanding of source and target systems
- Access to both environments during migration
- Downtime window approved (if required)
- Rollback plan documented
- Clinical staff communication plan
Migration Scenarios
| Scenario | Complexity | Downtime | Duration |
|---|
| Legacy CDS to OpenEvidence | High | 4-8 hours | 2-4 weeks |
| Add EHR Integration | Medium | None | 1-2 weeks |
| Multi-site Expansion | Medium | None | 1-2 weeks |
| API Version Upgrade | Low | None | 1-3 days |
Instructions
Scenario 1: Legacy CDS to OpenEvidence Migration
Step 1: Assessment and Planning
interface LegacySystemAssessment {
systemName: string;
queryVolume: {
dailyQueries: number;
peakQueriesPerMinute: number;
uniqueUsers: number;
};
features: {
clinicalQuery: boolean;
drugInfo: boolean;
guidelines: boolean;
deepResearch: boolean;
};
integrations: {
ehr: string[];
sso: string[];
audit: string[];
};
dataToMigrate: {
savedSearches: boolean;
userPreferences: boolean;
auditLogs: boolean;
};
}
async function assessLegacySystem(): Promise<LegacySystemAssessment> {
const queryLogs = await legacyDb.queryLogs.aggregate({
_count: { daily: true },
_max: { queriesPerMinute: },
});
users = legacyDb..();
{
: ,
: {
: queryLogs..,
: queryLogs..,
: users,
},
: {
: ,
: ,
: ,
: ,
},
: {
: [, ],
: [],
: [],
},
: {
: ,
: ,
: ,
},
};
}
Step 2: Parallel Running Period
interface ParallelConfig {
legacyClient: LegacyClient;
openEvidenceClient: OpenEvidenceClient;
comparisonRatio: number;
autoFallback: boolean;
}
export class ParallelRunner {
constructor(private config: ParallelConfig) {}
async query(question: string, context: any): Promise<{
result: any;
source: 'legacy' | 'openevidence';
comparison?: ComparisonResult;
}> {
const shouldCompare = Math.random() < this.config.comparisonRatio;
const oePromise = this.config.openEvidenceClient.query({
question,
context,
});
let legacyPromise: <> | = ;
(shouldCompare) {
legacyPromise = ...(question);
}
{
oeResult = oePromise;
(legacyPromise) {
legacyResult = legacyPromise.( );
(legacyResult) {
.(question, oeResult, legacyResult);
}
}
{
: oeResult,
: ,
};
} (error) {
(.. && legacyPromise) {
.();
legacyResult = legacyPromise;
{
: legacyResult,
: ,
};
}
error;
}
}
(
: ,
: ,
:
): <> {
: = {
: (),
: (question),
: {
: oeResult.,
: oeResult.,
: oeResult..,
},
: {
: legacyResult.,
: legacyResult.?. || ,
},
};
db..({ : comparison });
}
}
Step 3: Data Migration
interface MigrationJob {
id: string;
type: 'users' | 'preferences' | 'audit_logs';
status: 'pending' | 'running' | 'completed' | 'failed';
progress: number;
errors: string[];
}
export class DataMigrator {
async migrateUsers(): Promise<MigrationJob> {
const job = await this.createJob('users');
try {
const legacyUsers = await legacyDb.users.findMany();
let processed = 0;
for (const user of legacyUsers) {
try {
await db.users.upsert({
where: { email: user.email },
create: {
email: user.email,
firstName: user.firstName,
: user.,
: .(user.),
: ,
: (),
},
: {
: ,
: (),
},
});
} (: ) {
job..();
}
processed++;
job. = (processed / legacyUsers.) * ;
.(job);
}
job. = ;
.(job);
job;
} (: ) {
job. = ;
job..(error.);
.(job);
error;
}
}
(): <> {
job = .();
batchSize = ;
offset = ;
hasMore = ;
(hasMore) {
logs = legacyDb..({
: offset,
: batchSize,
});
(logs. === ) {
hasMore = ;
;
}
transformed = logs.( ({
: log.,
: log.,
: .(log.),
: ,
: log.,
: log.,
: ,
}));
db..({ : transformed });
offset += batchSize;
job. = .(, job. + );
.(job);
}
job. = ;
job. = ;
.(job);
job;
}
(: ): {
: <, > = {
: .,
: .,
: .,
: .,
};
mapping[legacyRole] || .;
}
(: ): {
: <, > = {
: ,
: ,
: ,
};
mapping[legacyAction] || legacyAction;
}
}
Scenario 2: EHR Integration (Epic)
Step 1: SMART on FHIR Configuration
interface SMARTConfig {
clientId: string;
clientSecret: string;
redirectUri: string;
scope: string[];
epicEndpoints: {
authorize: string;
token: string;
fhir: string;
};
}
export const epicConfig: SMARTConfig = {
clientId: process.env.EPIC_CLIENT_ID!,
clientSecret: process.env.EPIC_CLIENT_SECRET!,
redirectUri: `${process.env.APP_URL}/auth/epic/callback`,
scope: [
'openid',
'fhirUser',
'launch/patient',
'patient/Patient.read',
'patient/MedicationRequest.read',
'patient/Condition.read',
],
epicEndpoints: {
authorize: 'https://fhir.epic.com/interconnect-fhir-oauth/oauth2/authorize',
token: 'https://fhir.epic.com/interconnect-fhir-oauth/oauth2/token',
fhir: 'https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4',
},
};
Step 2: CDS Hooks Integration
import { Router } from 'express';
import { ClinicalEvidenceService } from '../../services/clinical';
const router = Router();
router.get('/cds-services', (req, res) => {
res.json({
services: [
{
id: 'openevidence-clinical-decision-support',
hook: 'patient-view',
title: 'OpenEvidence Clinical Decision Support',
description: 'AI-powered clinical evidence at the point of care',
prefetch: {
patient: 'Patient/{{context.patientId}}',
conditions: 'Condition?patient={{context.patientId}}',
medications: 'MedicationRequest?patient={{context.patientId}}&status=active',
},
},
{
id: 'openevidence-drug-interaction',
hook: 'medication-prescribe',
title: 'OpenEvidence Drug Interaction Check',
description: 'Check for drug interactions using AI clinical evidence',
prefetch: {
patient: 'Patient/{{context.patientId}}',
medications: ,
},
},
],
});
});
router.(, (req, res) => {
{ serviceId } = req.;
{ hook, context, prefetch } = req.;
{
: [] = [];
(serviceId) {
:
cards = (context, prefetch);
;
:
cards = (context, prefetch);
;
}
res.({ cards });
} (error) {
.(, error);
res.({ : [] });
}
});
(): <[]> {
conditions = prefetch.?.?.(
e..?.
).() || [];
(conditions. === ) {
[];
}
evidence = clinicalService.(
,
{
: ,
: ,
},
{ : , : }
);
[{
: crypto.(),
: ,
: evidence.,
: ,
: {
: ,
: ,
: ,
},
: [{
: ,
: ,
: ,
}],
}];
}
(): <[]> {
newMedication = context.?.[]?.?.?.;
currentMedications = prefetch.?.?.(
e..?.
).() || [];
(!newMedication || currentMedications. === ) {
[];
}
interaction = clinicalService.(
[newMedication, ...currentMedications],
{ : , : }
);
(!interaction.) {
[];
}
[{
: crypto.(),
: ,
: interaction.,
: interaction. === ? : ,
: {
: ,
: ,
},
: interaction. === ? [{
: ,
: crypto.(),
: ,
}] : [],
}];
}
router;
Scenario 3: Multi-Site Expansion
Step 1: Site Configuration
interface SiteConfig {
siteId: string;
siteName: string;
region: string;
openEvidenceOrgId: string;
ehrSystem: 'epic' | 'cerner' | 'meditech' | 'none';
features: {
deepConsult: boolean;
webhooks: boolean;
};
quotas: {
dailyQueries: number;
monthlyDeepConsults: number;
};
}
const SITE_CONFIGS: Record<string, SiteConfig> = {
'main-hospital': {
siteId: 'main-hospital',
siteName: 'Main Hospital',
region: 'us-central',
openEvidenceOrgId: 'org_main_***',
ehrSystem: 'epic',
features: { deepConsult: true, webhooks: true },
quotas: { dailyQueries: 10000, monthlyDeepConsults: 500 },
},
'clinic-network': {
: ,
: ,
: ,
: ,
: ,
: { : , : },
: { : , : },
},
: {
: ,
: ,
: ,
: ,
: ,
: { : , : },
: { : , : },
},
};
(): {
config = [siteId];
(!config) {
();
}
config;
}
Migration Checklist
Pre-Migration
During Migration
Post-Migration
Output
- Legacy system assessment
- Parallel running configuration
- Data migration scripts
- EHR integration (SMART on FHIR, CDS Hooks)
- Multi-site configuration
Error Handling
| Migration Issue | Detection | Resolution |
|---|
| Data corruption | Validation checks | Restore from backup |
| SSO failure | Auth errors | Verify IdP config |
| EHR integration fails | CDS Hooks errors | Check FHIR endpoints |
| Performance regression | Metrics comparison | Optimize or rollback |
Resources
Next Steps
Congratulations! You have completed the OpenEvidence skill pack. For ongoing support, contact support@openevidence.com or visit https://openevidence.com.