ERP Middleware - Boundary Contract
Purpose
Define the Day 1 contract between webshop and existing erp-middleware so ownership, reliability, and performance expectations are explicit.
Ownership
| Area |
Accountable |
Responsible |
Consulted |
| ERP business mapping rules |
ERP Middleware |
ERP Middleware |
Webshop |
| Runtime operations (scheduler/workers) |
Shared Ops |
Shared Ops |
ERP Middleware, Webshop |
| Contract versioning |
ERP Middleware + Webshop |
ERP Middleware + Webshop |
Shared Ops |
| Incident triage for sync failures |
Shared Ops |
Shared Ops |
ERP Middleware, Webshop |
Boundary Rules
webshop and erp-middleware own separate schemas.
- No direct cross-database reads/writes.
- Cross-island writes are propagated with outbox/inbox patterns and idempotency keys.
- Synchronous APIs are used for request/response use cases that need immediate feedback.
- Asynchronous events are used for eventual consistency updates and retries.
Domain Flows In Scope
- Customer create/update synchronization.
- Order create/update synchronization.
- Product price update ingestion from ERP.
- Invoice metadata and document retrieval.
- Payment status synchronization.
Sync API Contract (Day 1)
Webshop -> ERP Middleware
| Endpoint (suggested) |
Purpose |
Idempotency Key |
POST /erp/customers |
Create or upsert ERP customer |
customer:{tenantId}:{customerId}:{version} |
POST /erp/orders |
Create ERP order from webshop order |
order:{tenantId}:{orderId}:{version} |
POST /erp/orders/{orderId}/status |
Update ERP order status |
order-status:{tenantId}:{orderId}:{status}:{version} |
ERP Middleware -> Webshop
| Endpoint (suggested) |
Purpose |
Idempotency Key |
POST /webshop/orders/{orderId}/payment-status |
Push latest payment status |
payment-status:{orderId}:{status}:{externalVersion} |
POST /webshop/orders/{orderId}/invoice-available |
Notify invoice metadata availability |
invoice:{orderId}:{invoiceNumber}:{externalVersion} |
POST /webshop/products/prices |
Push ERP-originated price updates |
price:{articleNumber}:{priceList}:{externalVersion} |
Async Events Contract (Day 1)
Published by Webshop
| Event |
Payload Core Fields |
customer.upsert.requested.v1 |
tenant id, customer id, change version, changed fields |
order.created.v1 |
tenant id, order id, lines, totals, customer reference |
order.status.changed.v1 |
tenant id, order id, previous/new status, timestamp |
Published by ERP Middleware
| Event |
Payload Core Fields |
erp.customer.synced.v1 |
tenant id, customer id, external id, sync status |
erp.order.synced.v1 |
tenant id, order id, external id, sync status |
erp.invoice.available.v1 |
tenant id, order id, invoice id/number, document url or token |
erp.price.updated.v1 |
article number, price list id, amount, effective timestamp |
Reliability Model
- Outbox table per producer service for durable publish.
- Inbox deduplication table per consumer for idempotent processing.
- Exponential backoff retry with capped attempts.
- Dead-letter queue with operator replay command.
- Correlation ID propagated across sync and async calls.
Error Handling
| Error Type |
Expected Behavior |
Validation error (4xx) |
Reject payload, log structured error, no blind retry |
Temporary ERP/API failure (5xx or timeout) |
Retry with backoff and eventually DLQ |
| Contract version mismatch |
Route to compatibility handler or reject with explicit version error |
| Duplicate delivery |
Detect through idempotency key and acknowledge without side effects |
Security
- Service-to-service authentication required (mTLS or signed tokens).
- Secrets managed through platform secret manager, never in code.
- Audit log for all inbound/outbound ERP contract calls.
- Principle of least privilege for integration credentials.
SLO / SLI Targets
| Flow |
Target |
| Sync API success rate |
>= 99.5% (rolling 30 days) |
| Customer/order sync latency (event produced -> consumer committed) |
p95 < 2 minutes |
| Invoice availability propagation |
p95 < 5 minutes |
| Retry-to-success rate before DLQ |
>= 98% |
Operational Runbook Requirements
- Dashboard with per-flow throughput, failure, retry, and lag.
- Alert routing to Shared Ops (runtime) and ERP Middleware owner (domain impact).
- Replay command for DLQ records by tenant/order/customer scope.
- Manual reconciliation command for specific order/customer IDs.
Acceptance Scenarios (Gherkin)
Feature: ERP middleware boundary contract
Scenario: Customer upsert is idempotent
Given webshop sends customer upsert with idempotency key K
And ERP middleware already processed key K
When the same request is received again
Then ERP middleware should acknowledge without creating a duplicate customer
Scenario: Order sync retries on temporary failure
Given ERP middleware is temporarily unavailable
When webshop emits order.created.v1
Then processing should retry with backoff
And eventual success should publish erp.order.synced.v1
Scenario: Invoice event updates webshop order documents
Given ERP middleware publishes erp.invoice.available.v1 for an order
When webshop consumes the event
Then webshop should link invoice metadata to the order
And the customer invoice endpoint should expose the document