Four patterns for getting external data (ERP, MES, web apps, webhooks) into UMH.
| A: On-Demand | B: ERP → UNS | C: Local DB | D: HTTP API | |
|---|---|---|---|---|
| Direction | UMH pulls from ERP | ERP pushes to UNS | ERP syncs to DB | External POSTs to UMH |
| Record volume | High | Low (dozens) | High | Any |
| Latency | ~100-500ms | Instant read | Instant read | Instant write |
| Offline | No | Partial | Yes | No |
| Complexity | Low | Low | High (SQL) | Medium |
| Sync response | No | No | No | Yes (CRUD) |
| This repo | -- | -- | Implemented | Template |
Trigger (scan/button) → Bridge → HTTP GET to ERP → UNS
Query ERP in real-time when an event occurs. UNS stays lean — only active records become topics.
Best for: ERP has a usable API, too many records to pre-load, latency acceptable.
ERP (CDC/webhook/polling) → Bridge → UNS Topics → Consumers
ERP data pushed into UNS proactively. Each record becomes a topic.
Best for: Limited active records, ERP supports webhooks/CDC, multiple consumers need same data.
ERP (batch/CDC) → Dataflow → TimescaleDB (schema you control)
↑
Shopfloor Event → UNS → Consumer ──┘ (enrich via SQL join)
ERP data synced to local database. Events flow through UNS. Consumers join event data with master data at query time.
Best for: ERP has no real-time API, complex queries needed, thousands of records, offline resilience.
This repo implements this pattern with deduplication flows (erp_process.yaml) and persistence flows (erp_to_timescale.yaml). See flow templates.
umh.v1.{location}._entity.process ← Incoming from ERP
umh.v1.{location}._entity.create ← New record (after dedup)
umh.v1.{location}._entity.update ← Changed fields
umh.v1.{location}._entity.duplicate ← No change (dropped)
umh.v1.{location}._entity.delete ← Removal
External System ──POST──► NGINX ──► UMH Core (http_server) ──► UNS / DB
Create REST API endpoints directly inside UMH Core using Benthos http_server input. No separate backend needed — each endpoint is a dataflow listening on its own port, with NGINX routing external traffic.
Best for: Receiving webhooks, rapid prototyping, simple CRUD APIs, web app integrations.
Receive HTTP POST, transform, publish to UNS. No response body.
input:
http_server:
address: 0.0.0.0:8090
path: /api/v1/orders
allowed_verbs: [POST]
pipeline:
processors:
- bloblang: |
meta umh_topic = "umh.v1.mycompany.factory1._erp.orders"
root.orderId = this.data.id
root.status = this.event_type
output:
uns: {}Write directly to TimescaleDB. Good for updates that don't need event distribution.
input:
http_server:
address: 0.0.0.0:8091
path: /api/v1/stop-reason
allowed_verbs: [POST]
output:
sql_raw:
driver: postgres
dsn: ${DB_DSN}
query: UPDATE machine_stops SET stop_reason_id = $1 WHERE id = $2
args_mapping: "[this.reason_id, this.stop_id]"Handle POST/PUT/DELETE with JSON responses. Use sync_response for request-reply.
input:
http_server:
address: 0.0.0.0:8092
path: /api/v1/stop-reasons
allowed_verbs: [POST, PUT, DELETE]
sync_response:
headers:
Content-Type: application/json
pipeline:
processors:
- switch:
- check: meta("http_server_verb") == "POST"
processors:
- sql_raw:
query: INSERT INTO stop_reasons (name, category) VALUES ($1, $2) RETURNING *
args_mapping: "[this.name, this.category]"
- check: meta("http_server_verb") == "DELETE"
processors:
- sql_raw:
query: DELETE FROM stop_reasons WHERE id = $1 RETURNING id
args_mapping: "[this.id]"
output:
sync_response: {}Each http_server binds to a unique port. NGINX gives them clean external URLs:
location /api/v1/stop-reason { proxy_pass http://umh-core:8091; }
location /api/v1/stop-reasons { proxy_pass http://umh-core:8092; }
location /webhook/ { proxy_pass http://umh-core:8040; }The UNS is an event backbone, not a database. Publish state changes (order created, status changed), store master data where it can be queried efficiently. Mix patterns as needed — Pattern D for receiving, Pattern C for persistence.
- Data Modeling —
_rawvs data contracts - Historian — TimescaleDB schema and setup
- Deployment Lessons — DSN config, permissions
- Flow Templates — ERP dedup + persistence templates