Oil and gas operations run on data that never sleeps — pipeline pressure readings every 30 minutes, wellhead production rates every hour, BSEE/SEMS II audit deadlines that can't slip, OSHA PSM incident reports with 24-hour notification windows.
Most operators still handle this with spreadsheets, email chains, and manual shift handoffs. n8n changes that: self-hosted, git-versionable, and zero data egress to third-party cloud platforms — critical when SCADA telemetry, wellhead production data, and reservoir models are competitively sensitive and subject to CISA critical infrastructure requirements.
Here are 5 n8n workflows for oil and gas operations, complete with import-ready JSON.
1. Pipeline Pressure Anomaly Alert & PHMSA IMP Notification
The problem: Pipeline integrity management (IMP) under 49 CFR Part 195 requires operators to monitor pressure deviations and notify PHMSA within defined windows for significant anomalies. Manual monitoring misses overnight events and creates documentation gaps.
The workflow: Runs every 30 minutes. Reads pipeline segment data (current PSI vs MAWP) from Google Sheets or a SCADA historian. Classifies deviations: >10% = CRITICAL (PHMSA IMP notification required), >5% = WARNING. Routes critical alerts to Slack #pipeline-integrity, emails the on-call pipeline engineer, and logs to the IMP tracking sheet.
{"name": "Pipeline Pressure Anomaly Alert & PHMSA IMP Notification", "nodes": [{"name": "Schedule Trigger", "type": "n8n-nodes-base.scheduleTrigger", "parameters": {"rule": {"interval": [{"field": "minutes", "minutesInterval": 30}]}}, "position": [250, 300]}, {"name": "Read Pipeline Segments", "type": "n8n-nodes-base.googleSheets", "parameters": {"operation": "readRows", "sheetId": "{{PIPELINE_SEGMENTS_SHEET_ID}}", "options": {}}, "position": [450, 300]}, {"name": "Classify Pressure Deviation", "type": "n8n-nodes-base.code", "parameters": {"jsCode": "const items = [];\nfor (const item of $input.all()) {\n const seg = item.json;\n const curr = parseFloat(seg.current_psi || 0);\n const baseline = parseFloat(seg.mawp_psi || 0);\n if (baseline === 0) continue;\n const dev = Math.abs(curr - baseline) / baseline;\n let severity = 'OK';\n if (dev >= 0.10) severity = 'CRITICAL';\n else if (dev >= 0.05) severity = 'WARNING';\n if (severity !== 'OK') {\n items.push({ json: { ...seg, deviation_pct: (dev * 100).toFixed(2), severity, phmsa_imp_required: severity === 'CRITICAL', alert_ts: new Date().toISOString() } });\n }\n}\nreturn items;"}, "position": [650, 300]}, {"name": "Filter Non-OK", "type": "n8n-nodes-base.filter", "parameters": {"conditions": {"string": [{"value1": "={{$json.severity}}", "operation": "isNotEqual", "value2": "OK"}]}}, "position": [850, 300]}, {"name": "Slack Pipeline Integrity", "type": "n8n-nodes-base.slack", "parameters": {"channel": "#pipeline-integrity", "text": "={{$json.severity}} \u2014 Segment {{$json.segment_id}} ({{$json.pipeline_name}}): {{$json.deviation_pct}}% deviation from MAWP {{$json.mawp_psi}} PSI. Current: {{$json.current_psi}} PSI. PHMSA IMP required: {{$json.phmsa_imp_required}}"}, "position": [1050, 200]}, {"name": "Gmail Pipeline Engineer", "type": "n8n-nodes-base.gmail", "parameters": {"to": "={{$json.engineer_email}}", "subject": "[PIPELINE ALERT] {{$json.severity}} \u2014 {{$json.segment_id}} Pressure Deviation", "message": "Pipeline segment {{$json.segment_id}} on {{$json.pipeline_name}} has exceeded pressure deviation threshold.\n\nCurrent: {{$json.current_psi}} PSI\nMAWP: {{$json.mawp_psi}} PSI\nDeviation: {{$json.deviation_pct}}%\nSeverity: {{$json.severity}}\n\nPHMSA IMP notification required: {{$json.phmsa_imp_required}}\nTimestamp: {{$json.alert_ts}}\n\nPlease investigate immediately and log in IMP tracking system."}, "position": [1050, 400]}, {"name": "Log to IMP Tracker", "type": "n8n-nodes-base.googleSheets", "parameters": {"operation": "appendRow", "sheetId": "{{IMP_TRACKING_SHEET_ID}}", "options": {}, "fieldsUi": {"values": [{"fieldId": "segment_id", "fieldValue": "={{$json.segment_id}}"}, {"fieldId": "severity", "fieldValue": "={{$json.severity}}"}, {"fieldId": "deviation_pct", "fieldValue": "={{$json.deviation_pct}}"}, {"fieldId": "phmsa_imp_required", "fieldValue": "={{$json.phmsa_imp_required}}"}, {"fieldId": "alert_ts", "fieldValue": "={{$json.alert_ts}}"}]}}, "position": [1050, 550]}], "connections": {"Schedule Trigger": {"main": [[{"node": "Read Pipeline Segments", "type": "main", "index": 0}]]}, "Read Pipeline Segments": {"main": [[{"node": "Classify Pressure Deviation", "type": "main", "index": 0}]]}, "Classify Pressure Deviation": {"main": [[{"node": "Filter Non-OK", "type": "main", "index": 0}]]}, "Filter Non-OK": {"main": [[{"node": "Slack Pipeline Integrity", "type": "main", "index": 0}, {"node": "Gmail Pipeline Engineer", "type": "main", "index": 0}, {"node": "Log to IMP Tracker", "type": "main", "index": 0}]]}}}
Compliance angle: PHMSA 49 CFR §195.452 requires operators to notify PHMSA of significant pressure anomalies within 24 hours. This workflow creates a time-stamped IMP log entry automatically — your audit trail is built in.
2. Wellhead Production Variance Monitor (BSEE NTL Reporting)
The problem: BSEE Notice to Lessees (NTL 2010-G05) requires offshore operators to report production variances that exceed authorized rates. Manual tracking across dozens of wells creates reporting lag and compliance risk.
The workflow: Runs every hour. Reads well records (actual BBL vs authorized BBL/day). Calculates variance: >10% = CRITICAL (BSEE NTL threshold potentially breached), >5% = WARNING. Sends Slack alerts to #production-ops, emails the production engineer, and logs to the BSEE reporting sheet.
{"name": "Wellhead Production Variance Monitor (BSEE NTL)", "nodes": [{"name": "Schedule Trigger", "type": "n8n-nodes-base.scheduleTrigger", "parameters": {"rule": {"interval": [{"field": "hours", "hoursInterval": 1}]}}, "position": [250, 300]}, {"name": "Read Well Records", "type": "n8n-nodes-base.googleSheets", "parameters": {"operation": "readRows", "sheetId": "{{WELL_RECORDS_SHEET_ID}}", "options": {}}, "position": [450, 300]}, {"name": "Calc Production Variance", "type": "n8n-nodes-base.code", "parameters": {"jsCode": "const items = [];\nfor (const item of $input.all()) {\n const w = item.json;\n const actual = parseFloat(w.actual_bbl_today || 0);\n const auth = parseFloat(w.authorized_bbl_day || 0);\n if (auth === 0) continue;\n const variance = (actual - auth) / auth;\n const variancePct = (variance * 100).toFixed(2);\n let status = 'NORMAL';\n if (Math.abs(variance) > 0.10) status = 'CRITICAL_VARIANCE';\n else if (Math.abs(variance) > 0.05) status = 'WARNING_VARIANCE';\n if (status !== 'NORMAL') {\n items.push({ json: { ...w, variance_pct: variancePct, status, bsee_ntl_threshold: Math.abs(variance) > 0.10, alert_ts: new Date().toISOString() } });\n }\n}\nreturn items;"}, "position": [650, 300]}, {"name": "Slack Production Ops", "type": "n8n-nodes-base.slack", "parameters": {"channel": "#production-ops", "text": "={{$json.status}} \u2014 Well {{$json.well_id}} ({{$json.field_name}}): {{$json.variance_pct}}% variance from authorized rate. Actual: {{$json.actual_bbl_today}} BBL, Authorized: {{$json.authorized_bbl_day}} BBL/day. BSEE NTL reporting: {{$json.bsee_ntl_threshold}}"}, "position": [850, 200]}, {"name": "Gmail Production Engineer", "type": "n8n-nodes-base.gmail", "parameters": {"to": "={{$json.production_engineer_email}}", "subject": "[PRODUCTION VARIANCE] {{$json.status}} \u2014 {{$json.well_id}}", "message": "Well {{$json.well_id}} on {{$json.field_name}} has exceeded production variance threshold.\n\nActual: {{$json.actual_bbl_today}} BBL\nAuthorized: {{$json.authorized_bbl_day}} BBL/day\nVariance: {{$json.variance_pct}}%\nBSEE NTL threshold breached: {{$json.bsee_ntl_threshold}}\nTimestamp: {{$json.alert_ts}}\n\nReview production data and update BSEE reporting log if NTL threshold exceeded."}, "position": [850, 400]}, {"name": "Log BSEE Reporting", "type": "n8n-nodes-base.googleSheets", "parameters": {"operation": "appendRow", "sheetId": "{{BSEE_REPORTING_SHEET_ID}}", "options": {}, "fieldsUi": {"values": [{"fieldId": "well_id", "fieldValue": "={{$json.well_id}}"}, {"fieldId": "variance_pct", "fieldValue": "={{$json.variance_pct}}"}, {"fieldId": "bsee_ntl_threshold", "fieldValue": "={{$json.bsee_ntl_threshold}}"}, {"fieldId": "alert_ts", "fieldValue": "={{$json.alert_ts}}"}]}}, "position": [850, 550]}], "connections": {"Schedule Trigger": {"main": [[{"node": "Read Well Records", "type": "main", "index": 0}]]}, "Read Well Records": {"main": [[{"node": "Calc Production Variance", "type": "main", "index": 0}]]}, "Calc Production Variance": {"main": [[{"node": "Slack Production Ops", "type": "main", "index": 0}, {"node": "Gmail Production Engineer", "type": "main", "index": 0}, {"node": "Log BSEE Reporting", "type": "main", "index": 0}]]}}}
Key detail: The bsee_ntl_threshold flag in the log triggers a mandatory human review — n8n doesn't file the BSEE report (that requires human judgment), but it ensures no variance goes unnoticed.
3. BSEE / SEMS II / PHMSA Compliance Deadline Tracker
The problem: Offshore operators manage dozens of overlapping regulatory deadlines: SEMS II annual audits, BSEE well integrity certifications, API RP 14C process safety reviews, PHMSA IMP annual assessments, OSHA PSM PHA revalidations. Missing one can mean $50K+ daily fines.
The workflow: Runs weekdays at 7AM. Reads a compliance_deadlines Sheets table with regulation, deadline_date, responsible_party, and owner_email fields. Classifies: OVERDUE, CRITICAL (≤7 days), URGENT (≤14), WARNING (≤30), NOTICE (≤60). Routes OVERDUE/CRITICAL to Slack #hse-compliance with escalation language, emails the responsible party for all tiers.
{"name": "BSEE / SEMS II / PHMSA Compliance Deadline Tracker", "nodes": [{"name": "Daily 7AM", "type": "n8n-nodes-base.scheduleTrigger", "parameters": {"rule": {"interval": [{"field": "cronExpression", "expression": "0 7 * * 1-5"}]}}, "position": [250, 300]}, {"name": "Read Compliance Deadlines", "type": "n8n-nodes-base.googleSheets", "parameters": {"operation": "readRows", "sheetId": "{{COMPLIANCE_DEADLINES_SHEET_ID}}", "options": {}}, "position": [450, 300]}, {"name": "Classify Urgency", "type": "n8n-nodes-base.code", "parameters": {"jsCode": "const items = [];\nconst now = new Date();\nfor (const item of $input.all()) {\n const d = item.json;\n const due = new Date(d.deadline_date);\n const daysLeft = Math.floor((due - now) / 86400000);\n let tier = null;\n if (daysLeft < 0) tier = 'OVERDUE';\n else if (daysLeft <= 7) tier = 'CRITICAL';\n else if (daysLeft <= 14) tier = 'URGENT';\n else if (daysLeft <= 30) tier = 'WARNING';\n else if (daysLeft <= 60) tier = 'NOTICE';\n if (tier) items.push({ json: { ...d, days_left: daysLeft, tier, alert_ts: now.toISOString() } });\n}\nreturn items;"}, "position": [650, 300]}, {"name": "Route by Tier", "type": "n8n-nodes-base.switch", "parameters": {"dataType": "string", "value1": "={{$json.tier}}", "rules": {"rules": [{"value2": "OVERDUE", "output": 0}, {"value2": "CRITICAL", "output": 1}, {"value2": "URGENT", "output": 2}, {"value2": "WARNING", "output": 3}, {"value2": "NOTICE", "output": 4}]}}, "position": [850, 300]}, {"name": "Slack OVERDUE", "type": "n8n-nodes-base.slack", "parameters": {"channel": "#hse-compliance", "text": ":rotating_light: OVERDUE \u2014 {{$json.requirement_name}} ({{$json.regulation}}) was due {{$json.deadline_date}}. Owner: {{$json.responsible_party}}. ESCALATING TO VP Safety."}, "position": [1050, 100]}, {"name": "Slack CRITICAL", "type": "n8n-nodes-base.slack", "parameters": {"channel": "#hse-compliance", "text": ":red_circle: CRITICAL \u2014 {{$json.requirement_name}} ({{$json.regulation}}) due in {{$json.days_left}} days ({{$json.deadline_date}}). Owner: {{$json.responsible_party}}."}, "position": [1050, 250]}, {"name": "Slack URGENT", "type": "n8n-nodes-base.slack", "parameters": {"channel": "#hse-compliance", "text": ":large_orange_circle: URGENT \u2014 {{$json.requirement_name}} ({{$json.regulation}}) due in {{$json.days_left}} days. Owner: {{$json.responsible_party}}."}, "position": [1050, 400]}, {"name": "Gmail Owner", "type": "n8n-nodes-base.gmail", "parameters": {"to": "={{$json.owner_email}}", "subject": "[{{$json.tier}}] {{$json.requirement_name}} \u2014 {{$json.days_left}} days remaining", "message": "Compliance deadline approaching:\n\nRequirement: {{$json.requirement_name}}\nRegulation: {{$json.regulation}}\nDeadline: {{$json.deadline_date}}\nDays remaining: {{$json.days_left}}\nStatus: {{$json.tier}}\n\nPlease confirm completion status and update the compliance tracker."}, "position": [1050, 550]}], "connections": {"Daily 7AM": {"main": [[{"node": "Read Compliance Deadlines", "type": "main", "index": 0}]]}, "Read Compliance Deadlines": {"main": [[{"node": "Classify Urgency", "type": "main", "index": 0}]]}, "Classify Urgency": {"main": [[{"node": "Route by Tier", "type": "main", "index": 0}]]}, "Route by Tier": {"main": [[{"node": "Slack OVERDUE", "type": "main", "index": 0}], [{"node": "Slack CRITICAL", "type": "main", "index": 0}], [{"node": "Slack URGENT", "type": "main", "index": 0}], [{"node": "Gmail Owner", "type": "main", "index": 0}], [{"node": "Gmail Owner", "type": "main", "index": 0}]]}}}
What to track: Populate the sheet with SEMS II annual audit date, BSEE APD certification expiry, API RP 14C last review + 5-year revalidation, PHMSA IMP annual assessment, OSHA PHA revalidation (≤5 years), flare permit renewals, environmental monitoring report deadlines.
4. HSE Incident Report & OSHA PSM / BSEE Notification Pipeline
The problem: OSHA PSM (29 CFR §1910.119) requires immediate notification for catastrophic releases and fatalities. BSEE requires notification within 24 hours for serious injuries on OCS facilities. Paper-based reporting misses notification deadlines and creates incomplete OSHA 300 log entries.
The workflow: Triggered by webhook from a field incident reporting app (or manual HTTP POST). Classifies severity: FATALITY, SERIOUS_INJURY, RECORDABLE, FIRST_AID, NEAR_MISS. For fatal/serious incidents: fires Slack #safety-emergency immediately with notification deadline clock, auto-logs to the OSHA 300 Sheets log, emails the safety manager with the 24-hour report deadline calculated.
{"name": "HSE Incident Report & OSHA PSM / BSEE Notification Pipeline", "nodes": [{"name": "Webhook Incident Report", "type": "n8n-nodes-base.webhook", "parameters": {"path": "oilgas-incident", "httpMethod": "POST", "responseMode": "responseNode"}, "position": [250, 300]}, {"name": "Respond 200 OK", "type": "n8n-nodes-base.respondToWebhook", "parameters": {"responseCode": 200, "responseBody": "{\"status\":\"received\"}"}, "position": [450, 150]}, {"name": "Classify Incident", "type": "n8n-nodes-base.code", "parameters": {"jsCode": "const inc = $input.first().json;\nconst severity = inc.severity || 'NEAR_MISS';\nconst classMap = {\n 'FATALITY': { level: 1, osha300: true, bsee_notify: true, phmsa_notify: inc.involves_pipeline || false, notify_hours: 24 },\n 'SERIOUS_INJURY': { level: 2, osha300: true, bsee_notify: true, phmsa_notify: false, notify_hours: 24 },\n 'RECORDABLE': { level: 3, osha300: true, bsee_notify: false, phmsa_notify: false, notify_hours: 0 },\n 'FIRST_AID': { level: 4, osha300: false, bsee_notify: false, phmsa_notify: false, notify_hours: 0 },\n 'NEAR_MISS': { level: 5, osha300: false, bsee_notify: false, phmsa_notify: false, notify_hours: 0 }\n};\nconst cls = classMap[severity] || classMap['NEAR_MISS'];\nconst reportDeadline = cls.notify_hours > 0 ? new Date(Date.now() + cls.notify_hours * 3600000).toISOString() : null;\nreturn [{ json: { ...inc, classification: cls, severity, report_deadline: reportDeadline, incident_ts: new Date().toISOString() } }];"}, "position": [450, 350]}, {"name": "If Fatal/Serious", "type": "n8n-nodes-base.if", "parameters": {"conditions": {"number": [{"value1": "={{$json.classification.level}}", "operation": "smallerEqual", "value2": 2}]}}, "position": [650, 350]}, {"name": "Slack Safety Emergency", "type": "n8n-nodes-base.slack", "parameters": {"channel": "#safety-emergency", "text": ":sos: {{$json.severity}} INCIDENT \u2014 {{$json.location}} ({{$json.incident_ts}})\nDescription: {{$json.description}}\nBSEE notification required: {{$json.classification.bsee_notify}}\nPHMSA notification required: {{$json.classification.phmsa_notify}}\nReport deadline: {{$json.report_deadline}}\nContact: {{$json.reporter_name}} ({{$json.reporter_phone}})"}, "position": [850, 200]}, {"name": "Log OSHA 300", "type": "n8n-nodes-base.googleSheets", "parameters": {"operation": "appendRow", "sheetId": "{{OSHA_300_LOG_SHEET_ID}}", "options": {}, "fieldsUi": {"values": [{"fieldId": "incident_date", "fieldValue": "={{$json.incident_ts}}"}, {"fieldId": "location", "fieldValue": "={{$json.location}}"}, {"fieldId": "severity", "fieldValue": "={{$json.severity}}"}, {"fieldId": "description", "fieldValue": "={{$json.description}}"}, {"fieldId": "bsee_notify", "fieldValue": "={{$json.classification.bsee_notify}}"}, {"fieldId": "report_deadline", "fieldValue": "={{$json.report_deadline}}"}]}}, "position": [850, 400]}, {"name": "Gmail Safety Manager", "type": "n8n-nodes-base.gmail", "parameters": {"to": "={{$json.safety_manager_email}}", "subject": "[{{$json.severity}}] HSE Incident \u2014 {{$json.location}} \u2014 Immediate Action Required", "message": "An HSE incident has been reported:\n\nSeverity: {{$json.severity}}\nLocation: {{$json.location}}\nTimestamp: {{$json.incident_ts}}\nReported by: {{$json.reporter_name}}\nDescription: {{$json.description}}\n\nOSHA 300 logging: {{$json.classification.osha300}}\nBSEE notification required within {{$json.classification.notify_hours}}h: {{$json.classification.bsee_notify}}\nPHMSA notification required: {{$json.classification.phmsa_notify}}\nReport deadline: {{$json.report_deadline}}\n\nPlease initiate incident response protocol immediately."}, "position": [850, 550]}], "connections": {"Webhook Incident Report": {"main": [[{"node": "Respond 200 OK", "type": "main", "index": 0}, {"node": "Classify Incident", "type": "main", "index": 0}]]}, "Classify Incident": {"main": [[{"node": "If Fatal/Serious", "type": "main", "index": 0}]]}, "If Fatal/Serious": {"main": [[{"node": "Slack Safety Emergency", "type": "main", "index": 0}], [{"node": "Log OSHA 300", "type": "main", "index": 0}, {"node": "Gmail Safety Manager", "type": "main", "index": 0}]]}}}
Critical caveat: This workflow automates notification routing and documentation. The actual BSEE TIMS/PHMSA report must be filed by a qualified person — this workflow ensures the right people know within minutes, not hours.
5. Daily Field Operations & Production Briefing
The problem: Operations managers need a daily production summary before the morning call: gross BBL, deferred production, uptime by well, water cut trends. Compiling it from field data sheets takes 30 minutes every morning.
The workflow: Runs at 6AM daily. Reads production data from Google Sheets or a data warehouse. Calculates gross production, deferred BBL, average uptime %, average water cut %, producing vs shut-in well counts. Sends an HTML table to the operations manager and a one-line Slack summary to #field-ops.
{"name": "Daily Field Operations & Production Briefing", "nodes": [{"name": "Daily 6AM", "type": "n8n-nodes-base.scheduleTrigger", "parameters": {"rule": {"interval": [{"field": "cronExpression", "expression": "0 6 * * *"}]}}, "position": [250, 300]}, {"name": "Read Production Data", "type": "n8n-nodes-base.googleSheets", "parameters": {"operation": "readRows", "sheetId": "{{PRODUCTION_DATA_SHEET_ID}}", "options": {}}, "position": [450, 300]}, {"name": "Build KPI Report", "type": "n8n-nodes-base.code", "parameters": {"jsCode": "const rows = $input.all().map(i => i.json);\nconst totalBbl = rows.reduce((s, r) => s + parseFloat(r.daily_bbl_gross || 0), 0);\nconst deferredBbl = rows.reduce((s, r) => s + parseFloat(r.deferred_bbl || 0), 0);\nconst avgUptime = rows.length ? (rows.reduce((s, r) => s + parseFloat(r.uptime_pct || 0), 0) / rows.length).toFixed(1) : 0;\nconst avgWaterCut = rows.length ? (rows.reduce((s, r) => s + parseFloat(r.water_cut_pct || 0), 0) / rows.length).toFixed(1) : 0;\nconst activeWells = rows.filter(r => r.status === 'PRODUCING').length;\nconst shutInWells = rows.filter(r => r.status === 'SHUT_IN').length;\nconst html = '<h2>Daily Field Operations Briefing</h2><table border=1 cellpadding=4><tr><th>Metric</th><th>Value</th></tr>' +\n '<tr><td>Gross Production</td><td>' + totalBbl.toLocaleString() + ' BBL</td></tr>' +\n '<tr><td>Deferred Production</td><td>' + deferredBbl.toLocaleString() + ' BBL</td></tr>' +\n '<tr><td>Average Uptime</td><td>' + avgUptime + '%</td></tr>' +\n '<tr><td>Average Water Cut</td><td>' + avgWaterCut + '%</td></tr>' +\n '<tr><td>Producing Wells</td><td>' + activeWells + '</td></tr>' +\n '<tr><td>Shut-In Wells</td><td>' + shutInWells + '</td></tr>' +\n '</table>';\nreturn [{ json: { total_bbl: totalBbl, deferred_bbl: deferredBbl, avg_uptime: avgUptime, avg_water_cut: avgWaterCut, active_wells: activeWells, shut_in_wells: shutInWells, html_report: html, report_date: new Date().toISOString().split('T')[0] } }];"}, "position": [650, 300]}, {"name": "Gmail Operations Manager", "type": "n8n-nodes-base.gmail", "parameters": {"to": "operations-manager@company.com", "subject": "Daily Field Operations Briefing -- {{$json.report_date}}", "message": "={{$json.html_report}}", "options": {"appendAttribution": false}}, "position": [850, 250]}, {"name": "Slack Field Ops", "type": "n8n-nodes-base.slack", "parameters": {"channel": "#field-ops", "text": "Daily production: {{$json.total_bbl}} BBL gross | Deferred: {{$json.deferred_bbl}} BBL | Uptime: {{$json.avg_uptime}}% | Water cut: {{$json.avg_water_cut}}% | Wells: {{$json.active_wells}} producing / {{$json.shut_in_wells}} shut-in"}, "position": [850, 400]}], "connections": {"Daily 6AM": {"main": [[{"node": "Read Production Data", "type": "main", "index": 0}]]}, "Read Production Data": {"main": [[{"node": "Build KPI Report", "type": "main", "index": 0}]]}, "Build KPI Report": {"main": [[{"node": "Gmail Operations Manager", "type": "main", "index": 0}, {"node": "Slack Field Ops", "type": "main", "index": 0}]]}}}
Why self-hosted n8n for oil & gas?
| Concern | Zapier/Make | Self-hosted n8n |
|---|---|---|
| SCADA/wellhead data egress | Routes through US/EU cloud | Stays in your VPC/OT network |
| CISA critical infrastructure | No OT/IT separation | Deployable in air-gapped/OT-adjacent zones |
| Reservoir model confidentiality | Third-party processor under GDPR | Zero external data transfer |
| Audit trail for SEMS II | No git-versioned workflow history | Every change is a git commit |
| NERC CIP (power-adjacent ops) | Not compliant for bulk electric system | Self-hosted meets BES Cyber System isolation |
| Cost at 50k ops/mo | $50–200/mo | $0 (self-hosted) |
Get the full FlowKit n8n template library
These 5 workflows are examples of what you can build with n8n. If you want pre-built, ready-to-import templates for the most common automation use cases — email auto-response, lead capture, invoice generation, AI customer support, price monitoring, and more — check out the FlowKit n8n Template Store:
stripeai.gumroad.com — Individual templates $12–$29, full bundle $97.
All templates include the workflow JSON, setup guide, and example data — import to your n8n instance and customize in minutes.
Top comments (0)