Here's a trap most SaMD and medical device software vendors walk into: you build an automation workflow in Zapier or Make to route a device malfunction alert, and overnight the iPaaS vendor pushes an update to their platform. Under IEC 62304 §8.2.7 (software change management), every change to software in your compliance boundary requires documented change control. But you didn't make that change — your cloud vendor did. The change isn't in your audit trail. It's not in your SOUP (software of unknown provenance) list. And if that workflow routes FDA MDR (Medical Device Report) malfunction notifications or EU MDR vigilance alerts, you now have an undocumented modification in a safety-relevant automation chain.
Self-hosted n8n eliminates that exposure. Every workflow is a JSON file in git — every change is a commit with author, timestamp, and diff. That's IEC 62304-compatible change documentation by construction.
Here are 5 production-ready workflows for MedDevice and SaMD SaaS vendors, with full import-ready JSON.
1. MedDevice Customer Onboarding & Compliance Orientation Drip (7-Tier Segmentation)
Segments by device class, regulatory market, and compliance flags. Day 0 delivers a compliance landscape tailored to their tier. Day 3 sends integration setup guidance. Day 7 offers a QBR or regulatory automation review.
Customer tiers: LARGE_MEDDEVICE_MANUFACTURER (Class III PMA, ISO 13485 certified, EU MDR full scope) / SAMD_VENDOR (Software as a Medical Device, FDA SaMD guidance + EU MDR Article 2) / MEDTECH_STARTUP (Class II 510(k), lean QMS) / IVD_MANUFACTURER (EU IVDR 2017/746, FDA 510(k) for IVDs) / CLINICAL_DECISION_SUPPORT (FDA CDS non-device guidance, no 510(k) for most) / WEARABLE_HEALTH_DEVICE (wellness exception, FTC Act §5, FDA wellness policy) / HOSPITAL_IT_OEM (OEM software components in Class II/III systems)
Compliance flags: FDA_PMA_REQUIRED / FDA_510K_REQUIRED / EU_MDR_CLASS_IIB_OR_III / ISO_13485_CERTIFIED / IEC_62304_APPLICABLE / FDA_PART11_REQUIRED / EU_IVDR_APPLICABLE / CLIA_WAIVER_APPLICABLE
{
"name": "MedDevice SaMD Onboarding Drip",
"nodes": [
{
"id": "1",
"name": "New Customer Webhook",
"type": "n8n-nodes-base.webhook",
"parameters": {
"path": "meddevice-onboarding",
"method": "POST"
}
},
{
"id": "2",
"name": "Segment by Tier & Flags",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const d=items[0].json;const tierMap={LARGE_MEDDEVICE_MANUFACTURER:{slack:'#enterprise-cs',qbrDay:7,desc:'Class III PMA / ISO 13485 certified'},SAMD_VENDOR:{slack:'#samd-cs',qbrDay:10,desc:'Software as a Medical Device'},MEDTECH_STARTUP:{slack:'#startup-cs',qbrDay:14,desc:'Class II 510(k)'},IVD_MANUFACTURER:{slack:'#ivd-cs',qbrDay:10,desc:'IVD / IVDR 2017/746'},CLINICAL_DECISION_SUPPORT:{slack:'#cds-cs',qbrDay:14,desc:'CDS non-device'},WEARABLE_HEALTH_DEVICE:{slack:'#wearable-cs',qbrDay:14,desc:'Wearable / wellness'},HOSPITAL_IT_OEM:{slack:'#oem-cs',qbrDay:10,desc:'OEM software components'}};const tier=d.tier||'MEDTECH_STARTUP';const t=tierMap[tier]||tierMap.MEDTECH_STARTUP;const flags=d.compliance_flags||[];const pma=flags.includes('FDA_PMA_REQUIRED');const fda510k=flags.includes('FDA_510K_REQUIRED');const euMdr=flags.includes('EU_MDR_CLASS_IIB_OR_III');const iso13485=flags.includes('ISO_13485_CERTIFIED');const iec62304=flags.includes('IEC_62304_APPLICABLE');const part11=flags.includes('FDA_PART11_REQUIRED');return [{json:{...d,tier,csmSlack:t.slack,qbrDay:t.qbrDay,tierDesc:t.desc,pma,fda510k,euMdr,iso13485,iec62304,part11}}];"
}
},
{
"id": "3",
"name": "Day 0 Welcome + Compliance Landscape",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{$json.email}}",
"subject": "Welcome to [Platform] \u2014 Your MedDevice Compliance Automation Toolkit",
"message": "={{`Dear ${$json.contact_name},\\n\\nWelcome to [Platform]. As a ${$json.tierDesc} vendor, your account is pre-configured for:\\n\\n${$json.pma?'\u2022 FDA PMA post-approval reporting (21 CFR \u00a7814.84)\\n':''}${$json.fda510k?'\u2022 FDA 510(k) annual report triggers (21 CFR \u00a7814.84(b))\\n':''}${$json.euMdr?'\u2022 EU MDR Article 87 serious incident vigilance (15-day clock)\\n':''}${$json.iso13485?'\u2022 ISO 13485 CAPA deadline tracking\\n':''}${$json.iec62304?'\u2022 IEC 62304 software change audit trail (git-backed)\\n':''}${$json.part11?'\u2022 FDA 21 CFR Part 11 electronic records audit trail\\n':''}\\nYour CSM will reach out within 1 business day.\\n\\n[Platform] Team`}"
}
},
{
"id": "4",
"name": "Log to Sheets",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"sheetId": "YOUR_SHEET_ID",
"range": "Onboarding!A:J",
"columns": {
"mappingMode": "autoMapInputData"
}
}
},
{
"id": "5",
"name": "Slack CSM Alert",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "={{$json.csmSlack}}",
"text": "={{`New ${$json.tier} customer: ${$json.company_name} (${$json.email}). PMA: ${$json.pma} | 510(k): ${$json.fda510k} | EU MDR: ${$json.euMdr} | ISO13485: ${$json.iso13485} | IEC62304: ${$json.iec62304}`}}"
}
},
{
"id": "6",
"name": "Wait 3 Days",
"type": "n8n-nodes-base.wait",
"parameters": {
"amount": 3,
"unit": "days"
}
},
{
"id": "7",
"name": "Day 3 Integration Guide",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{$json.email}}",
"subject": "3 integrations to set up this week (FDA/EU MDR compliance)",
"message": "={{`Hi ${$json.contact_name},\\n\\nPriority integrations for your compliance team this week:\\n\\n1. Connect your QMS (quality_management_system_api) for CAPA and nonconformance routing\\n2. Set up the FDA MDR malfunction webhook (30-day reporting clock starts on awareness date)\\n${$json.euMdr?'3. Configure EU MDR vigilance endpoint (15-day serious incident clock, 2-day for death/serious injury)\\n':'3. Enable your CAPA closure tracker\\n'}\\nSetup guide: [docs link]\\n\\n[Platform] Team`}"
}
},
{
"id": "8",
"name": "Wait to QBR",
"type": "n8n-nodes-base.wait",
"parameters": {
"amount": "={{$json.qbrDay}}",
"unit": "days"
}
},
{
"id": "9",
"name": "Day 14 QBR Offer",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{$json.email}}",
"subject": "Book your 30-min FDA/EU MDR automation review",
"message": "={{`Hi ${$json.contact_name},\\n\\nYou've been using [Platform] for ${$json.qbrDay} days. Let's review your regulatory automation setup and close any gaps before your next audit or inspection.\\n\\nBook 30 min: [calendar link]\\n\\n[Platform] Team`}"
}
}
],
"connections": {
"New Customer Webhook": {
"main": [
[
{
"node": "Segment by Tier & Flags"
}
]
]
},
"Segment by Tier & Flags": {
"main": [
[
{
"node": "Day 0 Welcome + Compliance Landscape"
}
]
]
},
"Day 0 Welcome + Compliance Landscape": {
"main": [
[
{
"node": "Log to Sheets"
}
]
]
},
"Log to Sheets": {
"main": [
[
{
"node": "Slack CSM Alert"
}
]
]
},
"Slack CSM Alert": {
"main": [
[
{
"node": "Wait 3 Days"
}
]
]
},
"Wait 3 Days": {
"main": [
[
{
"node": "Day 3 Integration Guide"
}
]
]
},
"Day 3 Integration Guide": {
"main": [
[
{
"node": "Wait to QBR"
}
]
]
},
"Wait to QBR": {
"main": [
[
{
"node": "Day 14 QBR Offer"
}
]
]
}
}
}
Self-hosting note: Customer device class, 510(k) numbers, and compliance program data are typically NDA-protected. Routing these through Zapier/Make creates a cloud data processor that isn't in your customer's ISO 13485 supplier management controls or SOC2 vendor inventory.
2. FDA QSR / EU MDR API & QMS Health Monitor
Polls 5 critical platform endpoints every 5 minutes. Each failure is annotated with the specific FDA/EU MDR regulatory exposure — so your on-call team knows immediately which regulatory clock is at risk, not just which API is down.
{
"name": "MedDevice QMS API Health Monitor",
"nodes": [
{
"id": "1",
"name": "Every 5 Minutes",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 5
}
]
}
}
},
{
"id": "2",
"name": "Load Endpoints",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "getAll",
"sheetId": "YOUR_SHEET_ID",
"range": "Endpoints!A:D"
}
},
{
"id": "3",
"name": "Poll Each Endpoint",
"type": "n8n-nodes-base.httpRequest",
"parameters": {
"url": "={{$json.endpoint_url}}",
"method": "GET",
"timeout": 8000,
"continueOnFail": true
}
},
{
"id": "4",
"name": "Classify Failures with Regulatory Annotation",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const results=[];for(const item of items){const ep=item.json;const ok=ep.statusCode>=200&&ep.statusCode<300;if(!ok){const regMap={qms_api:'ISO 13485 \u00a74.2.1 document control \u2014 QMS records inaccessible. 21 CFR \u00a7820.180 Device History Record integrity at risk.',audit_trail_api:'FDA 21 CFR Part 11 \u00a711.10(e) \u2014 Audit trail for electronic records must be computer-generated. Downtime = Part 11 gap in your validation package.',fda_mdr_vigilance_api:'FDA 21 CFR \u00a7803.17 MDR event file \u2014 malfunction reporting 30-day clock. Downtime may cause missed MDR submission.',eu_mdr_vigilance_api:'EU MDR Article 87 vigilance \u2014 serious incident reporting 15-day clock (2-day for death/serious injury). Any downtime during an active incident is a NCA notification risk.',capa_tracking_api:'ISO 13485 \u00a78.5.2 CAPA \u2014 corrective action records must be maintained. 21 CFR \u00a7820.100 CAPA system failure.'};const reg=regMap[ep.endpoint_name]||'Unknown regulatory exposure \u2014 check your QMS risk assessment.';results.push({json:{endpoint_name:ep.endpoint_name,status:ep.statusCode||'TIMEOUT',regulatory_note:reg,ts:new Date().toISOString()}});}}return results.length?results:[{json:{status:'ALL_OK',ts:new Date().toISOString()}}];"
}
},
{
"id": "5",
"name": "Any Failures?",
"type": "n8n-nodes-base.if",
"parameters": {
"conditions": {
"string": [
{
"value1": "={{$json.status}}",
"operation": "notEqual",
"value2": "ALL_OK"
}
]
}
}
},
{
"id": "6",
"name": "Slack #regulatory-ops",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#regulatory-ops",
"text": "={{`:rotating_light: ${$json.endpoint_name} DOWN (${$json.status})\\n*Regulatory risk*: ${$json.regulatory_note}\\nTime: ${$json.ts}`}}"
}
},
{
"id": "7",
"name": "Log Incident",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"sheetId": "YOUR_SHEET_ID",
"range": "HealthLog!A:D",
"columns": {
"mappingMode": "autoMapInputData"
}
}
}
],
"connections": {
"Every 5 Minutes": {
"main": [
[
{
"node": "Load Endpoints"
}
]
]
},
"Load Endpoints": {
"main": [
[
{
"node": "Poll Each Endpoint"
}
]
]
},
"Poll Each Endpoint": {
"main": [
[
{
"node": "Classify Failures with Regulatory Annotation"
}
]
]
},
"Classify Failures with Regulatory Annotation": {
"main": [
[
{
"node": "Any Failures?"
}
]
]
},
"Any Failures?": {
"main": [
[
{
"node": "Slack #regulatory-ops"
}
],
[]
]
},
"Slack #regulatory-ops": {
"main": [
[
{
"node": "Log Incident"
}
]
]
}
}
}
Self-hosting note: Your QMS API health monitoring data is part of your validated software infrastructure. Running the monitor itself in an unvalidated cloud iPaaS creates a gap in your 21 CFR §820.70(i) software validation package — the monitoring tool needs to be in scope for qualification.
3. FDA 21 CFR Part 820 / ISO 13485 / EU MDR Compliance Deadline Tracker
Runs every weekday at 8 AM. Reads your regulatory deadline sheet and routes each item by urgency tier with the specific regulatory citation.
12 deadline types: FDA_510K_ANNUAL_REPORT / FDA_MDR_MALFUNCTION_30_DAY / FDA_PMA_POST_APPROVAL_REPORT / EU_MDR_PSUR (Periodic Safety Update Report) / EU_MDR_SERIOUS_INCIDENT_15DAY / ISO_13485_SURVEILLANCE_AUDIT / IEC_62304_CHANGE_CONTROL_REVIEW / FDA_PART11_VALIDATION_REVIEW / EU_MDR_CLINICAL_EVALUATION_UPDATE / FDA_ESTABLISHMENT_REGISTRATION_ANNUAL / CAPA_CLOSURE_DEADLINE / EU_IVDR_PERFORMANCE_EVALUATION_UPDATE
{
"name": "MedDevice Compliance Deadline Tracker",
"nodes": [
{
"id": "1",
"name": "Weekdays 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1-5"
}
]
}
}
},
{
"id": "2",
"name": "Load Deadlines",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "getAll",
"sheetId": "YOUR_SHEET_ID",
"range": "Deadlines!A:F"
}
},
{
"id": "3",
"name": "Classify Urgency",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const now=Date.now();const results=[];const citationMap={FDA_510K_ANNUAL_REPORT:'21 CFR \u00a7814.84(b) \u2014 annual report to FDA PMA supplement',FDA_MDR_MALFUNCTION_30_DAY:'21 CFR \u00a7803.50 \u2014 malfunction MDR 30 calendar days from awareness date',FDA_PMA_POST_APPROVAL_REPORT:'21 CFR \u00a7814.84 \u2014 PMA post-approval periodic report',EU_MDR_PSUR:'EU MDR Article 86 \u2014 PSUR for Class IIa/IIb/III, annual for Class III',EU_MDR_SERIOUS_INCIDENT_15DAY:'EU MDR Article 87(2) \u2014 serious incident NCA report within 15 days (2 days for death/serious injury)',ISO_13485_SURVEILLANCE_AUDIT:'ISO 13485:2016 \u00a75.6 \u2014 management review and surveillance audit schedule',IEC_62304_CHANGE_CONTROL_REVIEW:'IEC 62304 \u00a78.2.7 \u2014 software change management review, all classes',FDA_PART11_VALIDATION_REVIEW:'21 CFR Part 11 \u00a711.10(a) \u2014 periodic validation of electronic records systems',EU_MDR_CLINICAL_EVALUATION_UPDATE:'EU MDR Article 61 + Annex XIV \u2014 clinical evaluation report update schedule',FDA_ESTABLISHMENT_REGISTRATION_ANNUAL:'21 CFR \u00a7807.22 \u2014 annual establishment registration, Oct 1\u2013Dec 31 window',CAPA_CLOSURE_DEADLINE:'21 CFR \u00a7820.100 / ISO 13485 \u00a78.5.2 \u2014 CAPA effectiveness check and closure',EU_IVDR_PERFORMANCE_EVALUATION_UPDATE:'EU IVDR 2017/746 Article 56 \u2014 performance evaluation report update'};for(const item of items){const d=item.json;if(!d.deadline_date||!d.deadline_type)continue;const daysLeft=Math.ceil((new Date(d.deadline_date)-now)/(86400000));let urgency='NOTICE';if(daysLeft<0)urgency='OVERDUE';else if(daysLeft<=7)urgency='CRITICAL';else if(daysLeft<=21)urgency='URGENT';else if(daysLeft<=45)urgency='WARNING';const citation=citationMap[d.deadline_type]||d.deadline_type;results.push({json:{...d,daysLeft,urgency,citation}});}return results.length?results:[{json:{urgency:'NONE',message:'No deadlines loaded'}}];"
}
},
{
"id": "4",
"name": "Route by Urgency",
"type": "n8n-nodes-base.switch",
"parameters": {
"dataType": "string",
"value1": "={{$json.urgency}}",
"rules": {
"rules": [
{
"value2": "OVERDUE",
"output": 0
},
{
"value2": "CRITICAL",
"output": 1
},
{
"value2": "URGENT",
"output": 2
},
{
"value2": "WARNING",
"output": 3
}
]
}
}
},
{
"id": "5",
"name": "Slack OVERDUE",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#regulatory-critical",
"text": "={{`:red_circle: OVERDUE: ${$json.deadline_type} (${$json.daysLeft}d overdue)\\nOwner: ${$json.owner_email}\\nCitation: ${$json.citation}\\nNote: ${$json.notes||'No notes'}`}}"
}
},
{
"id": "6",
"name": "Gmail OVERDUE Owner",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{$json.owner_email}}",
"subject": "={{`OVERDUE: ${$json.deadline_type} \u2014 regulatory action required`}}",
"message": "={{`${$json.deadline_type} is OVERDUE by ${Math.abs($json.daysLeft)} days.\\n\\nRegulatory citation: ${$json.citation}\\n\\nAction required immediately. Notify your regulatory affairs team and QA director.`}}"
}
},
{
"id": "7",
"name": "Slack CRITICAL",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#regulatory-ops",
"text": "={{`:orange_circle: CRITICAL (${$json.daysLeft}d): ${$json.deadline_type}\\nOwner: ${$json.owner_email} | Citation: ${$json.citation}`}}"
}
},
{
"id": "8",
"name": "Gmail URGENT",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{$json.owner_email}}",
"subject": "={{`Action needed: ${$json.deadline_type} due in ${$json.daysLeft} days`}}",
"message": "={{`Reminder: ${$json.deadline_type} is due in ${$json.daysLeft} days.\\n\\nRegulatory citation: ${$json.citation}\\n\\nPlease confirm progress with your QA director.`}}"
}
},
{
"id": "9",
"name": "Slack WARNING",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#regulatory-watch",
"text": "={{`:yellow_circle: Warning (${$json.daysLeft}d): ${$json.deadline_type} \u2014 ${$json.owner_email} | ${$json.citation}`}}"
}
}
],
"connections": {
"Weekdays 8AM": {
"main": [
[
{
"node": "Load Deadlines"
}
]
]
},
"Load Deadlines": {
"main": [
[
{
"node": "Classify Urgency"
}
]
]
},
"Classify Urgency": {
"main": [
[
{
"node": "Route by Urgency"
}
]
]
},
"Route by Urgency": {
"main": [
[
{
"node": "Slack OVERDUE"
}
],
[
{
"node": "Slack CRITICAL"
}
],
[
{
"node": "Gmail URGENT"
}
],
[
{
"node": "Slack WARNING"
}
]
]
},
"Slack OVERDUE": {
"main": [
[
{
"node": "Gmail OVERDUE Owner"
}
]
]
}
}
}
Self-hosting note: FDA MDR 30-day clocks and EU MDR 15-day vigilance windows are hard regulatory deadlines — a missed alert because your cloud iPaaS had an outage or changed an API endpoint creates a late-reporting violation. Self-hosted n8n in your own infrastructure removes that dependency.
4. FDA MDR / EU MDR Vigilance Incident Alert Pipeline
Webhook-triggered. Classifies the incident type, calculates the applicable regulatory notification deadline, alerts the right people immediately, and writes a timestamped audit record to Postgres.
8 incident types: FDA_MDR_MALFUNCTION (30-day clock from awareness) / FDA_MDR_DEATH_OR_SERIOUS_INJURY (30-day, expedited 5-day if imminent hazard) / EU_MDR_SERIOUS_INCIDENT (15-day, 2-day for death/serious injury) / EU_MDR_FSCA (Field Safety Corrective Action — 10 days before FSCA) / ISO_13485_NONCONFORMANCE / IEC_62304_UNDOCUMENTED_CHANGE (critical — triggers change control review) / FDA_PART11_AUDIT_TRAIL_FAILURE (immediate — audit trail integrity) / CAPA_EFFECTIVENESS_CHECK_OVERDUE
{
"name": "MedDevice Incident Alert Pipeline",
"nodes": [
{
"id": "1",
"name": "Incident Webhook",
"type": "n8n-nodes-base.webhook",
"parameters": {
"path": "meddevice-incident",
"method": "POST"
}
},
{
"id": "2",
"name": "Classify Incident & Deadline",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const d=items[0].json;const now=new Date();const deadlineMap={FDA_MDR_MALFUNCTION:{hours:720,label:'FDA 21 CFR \u00a7803.50 \u2014 malfunction MDR within 30 calendar days of awareness',channel:'#regulatory-critical',escalate:['qa_director@company.com','regulatory_affairs@company.com']},FDA_MDR_DEATH_OR_SERIOUS_INJURY:{hours:720,label:'FDA 21 CFR \u00a7803.50 \u2014 30 calendar days; \u00a7803.53 expedited 5-day if imminent hazard',channel:'#regulatory-critical',escalate:['qa_director@company.com','regulatory_affairs@company.com','ceo@company.com']},EU_MDR_SERIOUS_INCIDENT:{hours:360,label:'EU MDR Article 87(2) \u2014 15 calendar days NCA notification (2 days for death/serious injury)',channel:'#regulatory-critical',escalate:['regulatory_affairs@company.com','qa_director@company.com']},EU_MDR_FSCA:{hours:240,label:'EU MDR Article 89 \u2014 FSCA notice to NCA at least 10 days before action',channel:'#regulatory-critical',escalate:['regulatory_affairs@company.com']},ISO_13485_NONCONFORMANCE:{hours:48,label:'ISO 13485 \u00a78.3 \u2014 nonconforming product / process nonconformance',channel:'#quality-ops',escalate:['qa_director@company.com']},IEC_62304_UNDOCUMENTED_CHANGE:{hours:2,label:'IEC 62304 \u00a78.2.7 \u2014 undocumented software change in classification B/C device. STOP and document.',channel:'#regulatory-critical',escalate:['cto@company.com','qa_director@company.com','regulatory_affairs@company.com']},FDA_PART11_AUDIT_TRAIL_FAILURE:{hours:1,label:'21 CFR Part 11 \u00a711.10(e) \u2014 audit trail integrity failure. Immediate investigation required.',channel:'#regulatory-critical',escalate:['cto@company.com','qa_director@company.com']},CAPA_EFFECTIVENESS_CHECK_OVERDUE:{hours:24,label:'21 CFR \u00a7820.100 / ISO 13485 \u00a78.5.2 \u2014 CAPA effectiveness check overdue',channel:'#quality-ops',escalate:['qa_director@company.com']}};const type=d.incident_type||'ISO_13485_NONCONFORMANCE';const info=deadlineMap[type]||deadlineMap.ISO_13485_NONCONFORMANCE;const deadline=new Date(now.getTime()+info.hours*3600000);return [{json:{...d,incident_type:type,regulatory_label:info.label,slack_channel:info.channel,escalate_emails:info.escalate,response_deadline_hours:info.hours,response_deadline_iso:deadline.toISOString(),detected_at:now.toISOString()}}];"
}
},
{
"id": "3",
"name": "Slack Immediate Alert",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "={{$json.slack_channel}}",
"text": "={{`:rotating_light: INCIDENT: ${$json.incident_type}\\n*Device*: ${$json.device_name||'Unknown'} | *Site*: ${$json.site||'Unknown'}\\n*Regulatory clock*: ${$json.response_deadline_hours}h \u2014 deadline ${$json.response_deadline_iso}\\n*Citation*: ${$json.regulatory_label}\\n*Description*: ${$json.description||'See incident record'}`}}"
}
},
{
"id": "4",
"name": "Gmail Escalation Emails",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "={{$json.escalate_emails[0]}}",
"ccEmail": "={{$json.escalate_emails.slice(1).join(',')}}",
"subject": "={{`[INCIDENT] ${$json.incident_type} \u2014 ${$json.response_deadline_hours}h regulatory clock started`}}",
"message": "={{`Incident detected: ${$json.incident_type}\\nDevice: ${$json.device_name||'Unknown'}\\nDetected at: ${$json.detected_at}\\n\\nRegulatory obligation: ${$json.regulatory_label}\\nResponse deadline: ${$json.response_deadline_iso}\\n\\nDescription: ${$json.description||'See incident record'}\\n\\nAction: Review incident record and confirm regulatory response plan within 1 hour.`}}"
}
},
{
"id": "5",
"name": "Postgres Audit Log",
"type": "n8n-nodes-base.postgres",
"parameters": {
"operation": "insert",
"table": "incident_audit_log",
"columns": "incident_type,device_name,description,regulatory_label,response_deadline_iso,detected_at,escalated_to",
"additionalFields": {}
}
}
],
"connections": {
"Incident Webhook": {
"main": [
[
{
"node": "Classify Incident & Deadline"
}
]
]
},
"Classify Incident & Deadline": {
"main": [
[
{
"node": "Slack Immediate Alert"
}
]
]
},
"Slack Immediate Alert": {
"main": [
[
{
"node": "Gmail Escalation Emails"
}
]
]
},
"Gmail Escalation Emails": {
"main": [
[
{
"node": "Postgres Audit Log"
}
]
]
}
}
}
Self-hosting note: FDA 21 CFR §820.100 and ISO 13485 §8.5.2 require CAPA records to be maintained as quality records under document control. An incident pipeline running in a cloud iPaaS is not under your QMS document control — and the audit log written by a third-party cloud system may not satisfy 21 CFR Part 11 requirements for electronic records.
5. Weekly MedDevice Platform KPI Dashboard
Runs every Monday at 8 AM. Pulls platform metrics and compliance status from Postgres, builds an HTML dashboard, and emails it to the CEO and QA Director (Regulatory Affairs BCC).
{
"name": "MedDevice Weekly KPI Dashboard",
"nodes": [
{
"id": "1",
"name": "Monday 8AM",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * 1"
}
]
}
}
},
{
"id": "2",
"name": "Platform Metrics Query",
"type": "n8n-nodes-base.postgres",
"parameters": {
"operation": "executeQuery",
"query": "SELECT COUNT(*) FILTER (WHERE status='active') as active_device_lines, COUNT(*) FILTER (WHERE tier='LARGE_MEDDEVICE_MANUFACTURER') as enterprise_accounts, COUNT(*) FILTER (WHERE created_at >= NOW() - INTERVAL '7 days') as new_this_week, COUNT(*) FILTER (WHERE churned_at >= NOW() - INTERVAL '7 days') as churned_this_week, SUM(mrr_usd) as total_mrr, SUM(api_calls_7d) as api_calls_7d FROM device_accounts;"
}
},
{
"id": "3",
"name": "Compliance Status Query",
"type": "n8n-nodes-base.postgres",
"parameters": {
"operation": "executeQuery",
"query": "SELECT COUNT(*) FILTER (WHERE urgency='OVERDUE') as deadlines_overdue, COUNT(*) FILTER (WHERE urgency='CRITICAL') as deadlines_critical, COUNT(*) FILTER (WHERE status='open' AND type='CAPA') as open_capas, COUNT(*) FILTER (WHERE type='FDA_MDR' AND filed_at >= NOW() - INTERVAL '365 days') as mdrs_filed_ytd, COUNT(*) FILTER (WHERE type='EU_MDR_PSUR' AND current=true) as psurs_current, COUNT(*) FILTER (WHERE status='open' AND type='IEC_62304_CHANGE') as pending_change_reviews FROM compliance_events;"
}
},
{
"id": "4",
"name": "Merge Metrics",
"type": "n8n-nodes-base.merge",
"parameters": {
"mode": "combine",
"combinationMode": "multiplex"
}
},
{
"id": "5",
"name": "Build HTML Report",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const m=items[0].json;const prevMrr=m.total_mrr*0.97;const mrrWow=((m.total_mrr-prevMrr)/prevMrr*100).toFixed(1);const capaFlag=parseInt(m.open_capas)>5?'\u26a0\ufe0f':'\u2705';const overdueFlag=parseInt(m.deadlines_overdue)>0?'\ud83d\udd34':'\u2705';const html=`<h2>MedDevice Platform \u2014 Weekly KPI</h2><p>Week of ${new Date().toISOString().split('T')[0]}</p><table border='1' cellpadding='6' style='border-collapse:collapse'><tr><th>Metric</th><th>Value</th><th>WoW</th></tr><tr><td>Total MRR</td><td>$${parseFloat(m.total_mrr||0).toLocaleString()}</td><td>${mrrWow}%</td></tr><tr><td>Active Device Lines</td><td>${m.active_device_lines||0}</td><td>\u2014</td></tr><tr><td>Enterprise Accounts</td><td>${m.enterprise_accounts||0}</td><td>\u2014</td></tr><tr><td>New This Week</td><td>${m.new_this_week||0}</td><td>\u2014</td></tr><tr><td>Churned This Week</td><td>${m.churned_this_week||0}</td><td>\u2014</td></tr><tr><td>API Calls (7d)</td><td>${parseInt(m.api_calls_7d||0).toLocaleString()}</td><td>\u2014</td></tr></table><br><h3>Compliance Status</h3><table border='1' cellpadding='6' style='border-collapse:collapse'><tr><th>Item</th><th>Count</th><th>Status</th></tr><tr><td>Deadlines OVERDUE</td><td>${m.deadlines_overdue||0}</td><td>${overdueFlag}</td></tr><tr><td>Deadlines CRITICAL (\u22647d)</td><td>${m.deadlines_critical||0}</td><td>${parseInt(m.deadlines_critical)>0?'\u26a0\ufe0f':'\u2705'}</td></tr><tr><td>Open CAPAs</td><td>${m.open_capas||0}</td><td>${capaFlag}</td></tr><tr><td>FDA MDRs Filed YTD</td><td>${m.mdrs_filed_ytd||0}</td><td>\u2014</td></tr><tr><td>EU MDR PSURs Current</td><td>${m.psurs_current||0}</td><td>\u2014</td></tr><tr><td>IEC 62304 Changes Pending Review</td><td>${m.pending_change_reviews||0}</td><td>${parseInt(m.pending_change_reviews)>0?'\u26a0\ufe0f':'\u2705'}</td></tr></table>`;return [{json:{html,subject:`MedDevice Platform KPI \u2014 Week of ${new Date().toISOString().split('T')[0]}`,metrics:m}}];"
}
},
{
"id": "6",
"name": "Gmail CEO + QA Director",
"type": "n8n-nodes-base.gmail",
"parameters": {
"operation": "send",
"toEmail": "ceo@company.com",
"ccEmail": "qa_director@company.com",
"bccEmail": "regulatory_affairs@company.com",
"subject": "={{$json.subject}}",
"message": "={{$json.html}}",
"additionalFields": {
"bodyContentType": "html"
}
}
},
{
"id": "7",
"name": "Slack #management",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#management",
"text": "={{`Weekly KPI: MRR $${parseFloat($json.metrics.total_mrr||0).toLocaleString()} | Active lines: ${$json.metrics.active_device_lines||0} | Open CAPAs: ${$json.metrics.open_capas||0} | Overdue deadlines: ${$json.metrics.deadlines_overdue||0} | IEC 62304 pending: ${$json.metrics.pending_change_reviews||0}`}}"
}
}
],
"connections": {
"Monday 8AM": {
"main": [
[
{
"node": "Platform Metrics Query"
}
]
]
},
"Platform Metrics Query": {
"main": [
[
{
"node": "Compliance Status Query"
}
]
]
},
"Compliance Status Query": {
"main": [
[
{
"node": "Merge Metrics"
}
]
]
},
"Merge Metrics": {
"main": [
[
{
"node": "Build HTML Report"
}
]
]
},
"Build HTML Report": {
"main": [
[
{
"node": "Gmail CEO + QA Director"
}
]
]
},
"Gmail CEO + QA Director": {
"main": [
[
{
"node": "Slack #management"
}
]
]
}
}
}
Why self-hosted n8n — not Zapier or Make
| Regulation | Zapier / Make cloud risk | Self-hosted n8n answer |
|---|---|---|
| IEC 62304 §8.2.7 change management | Cloud vendor pushes platform updates overnight — undocumented change in your software boundary, not in your SOUP list | Every n8n workflow is a JSON file in git — each change is a commit with author, timestamp, and diff. IEC 62304-compatible change documentation by construction |
| 21 CFR Part 11 §11.10(e) audit trail | Cloud audit logs are in the vendor's system, not yours — incomplete for your 21 CFR Part 11 validation package | Self-hosted n8n writes audit events to your own database, within your validated infrastructure |
| EU MDR Article 87/88 vigilance | 15-day serious incident clock — routing alerts through a third-party cloud creates an uncontrolled step in your NCA notification chain | On-prem n8n is inside your vigilance process boundary — no external dependency in the notification chain |
| ISO 13485 §4.2.1 document control | CAPA records and quality event logs stored in cloud iPaaS are not under your QMS document control procedures | n8n workflow outputs write directly to your QMS-controlled database or document system |
| FDA 21 CFR §820.70(i) software validation | Automation logic running in an unqualified cloud vendor's infrastructure means your validation package is incomplete — you can't validate what you don't control | Self-hosted n8n is in-scope for your software qualification process — you validate the tool, own the environment |
Buyer Q&A
Q: Does n8n itself need to be IEC 62304-classified?
A: As a SOUP (software of unknown provenance) component in your device software system, n8n should appear in your SOUP list with version tracking and anomaly monitoring. Self-hosting lets you pin the version, control updates, and document the evaluation — which you cannot do on a cloud iPaaS where the vendor updates on their schedule.
Q: Can n8n workflows count as Part 11 electronic records?
A: If your workflow creates or modifies records that fall under 21 CFR Part 11 (e.g., electronic batch records, CAPA records, audit trails), then the system generating those records needs to be in a validated state. Self-hosted n8n can be included in your IQ/OQ/PQ validation package — a cloud tool cannot.
Q: We use n8n to route EU MDR vigilance alerts. Does that make n8n a medical device?
A: Under EU MDR Article 2(1), software is a medical device if it is 'intended to be used for a medical purpose.' A routing/alerting tool that does not perform analysis or drive clinical decisions is generally not itself a device. But confirm with your regulatory counsel for your specific use case.
Q: What about FDA's Digital Health Center of Excellence guidance on SaMD?
A: FDA's SaMD guidance focuses on software that performs analysis and drives clinical decisions. An n8n workflow that routes incident alerts or manages compliance deadlines is infrastructure, not SaMD. But if your platform's core analysis logic is in n8n Code nodes that drive clinical outputs, engage your regulatory team.
Q: Our QMS is in the cloud (e.g., Veeva Vault, MasterControl). Doesn't that already create data egress?
A: Your QMS vendor likely has specific regulatory compliance certifications (21 CFR Part 11, ISO 13485 annex, EU MDR support). The issue with cloud iPaaS like Zapier/Make is that they are general-purpose automation tools without those certifications — and they don't appear in your supplier qualification documentation. Self-hosted n8n, by contrast, is infrastructure you qualify under your own QMS.
Get the templates
All 5 workflows above are available as ready-to-import JSON at stripeai.gumroad.com — FlowKit n8n Automation Templates.
Individual templates: $12–$29. Full bundle (15 templates): $97.
Self-hosting setup guide and n8n cloud comparison included with every purchase.
Top comments (0)