Production plan integration with MES fails due to batch ID mismatch between systems

We’re having integration failures between SAP S/4HANA production planning and our MES (Manufacturing Execution System). The problem occurs specifically when production orders are updated - the batch ID format differences between systems cause sync errors.

SAP generates batch IDs in format ‘BATCH-2025-001234’ while our MES uses numeric format ‘20250001234’. We’ve tried implementing custom mapping logic in the integration middleware to transform between formats, but sync errors persist on order updates.

The error appears when MES tries to update production order status back to SAP:

{
  "orderId": "PO-45678",
  "batchId": "20250001234",
  "status": "IN_PROGRESS",
  "error": "Batch ID not found in SAP system"
}

Initial order creation from SAP to MES works fine with our transformation, but the reverse sync when MES updates order progress fails. Has anyone resolved bidirectional batch ID synchronization with different format requirements?

Your batch ID synchronization issue requires a comprehensive bidirectional mapping strategy with proper data persistence and lookup mechanisms. Let me provide a complete solution that addresses all three key aspects you’ve encountered.

Understanding the Batch ID Format Differences: The core problem is that SAP S/4HANA uses alphanumeric batch IDs (‘BATCH-2025-001234’) while your MES system uses pure numeric format (‘20250001234’). Your custom mapping logic handles the outbound transformation (SAP to MES) successfully, but fails on the inbound updates (MES to SAP) because the reverse lookup mechanism is either missing or incomplete.

Why Sync Errors Occur on Order Updates: When MES sends status updates back to SAP with batch ID ‘20250001234’, SAP cannot find this batch because it only knows ‘BATCH-2025-001234’. The error “Batch ID not found in SAP system” occurs because your middleware isn’t translating the MES format back to SAP format before forwarding the update. Even though your initial transformation worked, you need a persistent mapping that works in both directions.

Addressing Your Custom Mapping Logic Issues: Your attempted custom mapping likely transforms on-the-fly during outbound sync but doesn’t store the relationship for inbound lookups. This is a common mistake in integration design. The solution requires three components:

Complete Solution Architecture:

  1. Implement Persistent Mapping Table: Create a database table in your integration middleware with the following structure:
  • SAP_BATCH_ID (varchar, primary key): ‘BATCH-2025-001234’
  • MES_BATCH_ID (varchar, unique index): ‘20250001234’
  • PRODUCTION_ORDER_ID (varchar): ‘PO-45678’
  • CREATED_DATE (timestamp)
  • LAST_SYNC_DATE (timestamp)
  1. Outbound Sync Logic (SAP to MES):

// Pseudocode - Outbound transformation:
1. Receive production order from SAP with batch 'BATCH-2025-001234'
2. Transform to MES format: remove 'BATCH-', remove hyphens = '20250001234'
3. Store mapping: INSERT INTO batch_mapping (SAP_BATCH_ID, MES_BATCH_ID, PRODUCTION_ORDER_ID)
4. Send transformed order to MES with numeric batch ID
5. Log successful mapping creation
// Reference: Integration Middleware Design Pattern Guide
  1. Inbound Sync Logic (MES to SAP):

// Pseudocode - Inbound transformation:
1. Receive order update from MES with batch '20250001234'
2. Query mapping table: SELECT SAP_BATCH_ID WHERE MES_BATCH_ID = '20250001234'
3. Transform update payload to use SAP format 'BATCH-2025-001234'
4. Forward update to SAP with correct batch ID
5. Update LAST_SYNC_DATE in mapping table
// Handle missing mappings with error notification
  1. Performance Optimization with Caching: Implement an in-memory cache layer for the mapping table:
  • Load entire mapping table into memory on middleware startup
  • Use HashMap/Dictionary structure for O(1) lookup performance
  • Key by MES_BATCH_ID for inbound lookups, by SAP_BATCH_ID for outbound
  • Refresh cache when new mappings are created
  • Set cache TTL to 24 hours with event-based invalidation

For hundreds of updates per hour, cached lookups will complete in microseconds versus milliseconds for database queries.

  1. Handle Edge Cases:
  • Missing Mappings: If inbound update references a batch ID not in the mapping table, log error and trigger reconciliation process
  • Duplicate Creation: Use database constraints to prevent duplicate mappings
  • Orphaned Mappings: Implement cleanup job to remove mappings for completed/archived orders
  • Concurrent Updates: Use database transactions when creating mappings to prevent race conditions
  1. Monitoring and Validation:
  • Log all mapping operations (create, lookup success, lookup failure)
  • Implement alerts for missing mappings during inbound sync
  • Create dashboard showing mapping table size and lookup performance
  • Run daily reconciliation comparing SAP and MES batch records

Implementation Steps:

  1. Create the mapping database table in your middleware
  2. Modify outbound integration flow to store mappings after transformation
  3. Implement caching layer with initialization from database
  4. Update inbound integration flow to lookup and transform batch IDs
  5. Add error handling for missing mappings
  6. Test with sample orders covering both directions
  7. Deploy and monitor initial production batch

Critical Success Factor: The key is ensuring that EVERY outbound production order creation stores the bidirectional mapping immediately. If mappings are missing, inbound updates will fail. Implement validation to confirm mapping exists before considering outbound sync successful.

This approach eliminates the batch ID mismatch issue while maintaining acceptable performance for your update volume. The persistent mapping table becomes your single source of truth for ID translation in both directions.

Another angle to consider: verify that your custom mapping logic is actually persisting the bidirectional relationship. I’ve seen cases where the transformation happens correctly during SAP-to-MES sync, but the reverse mapping isn’t stored anywhere. Your middleware transforms ‘BATCH-2025-001234’ to ‘20250001234’ going out, but when ‘20250001234’ comes back from MES, there’s no stored relationship to convert it back. You need to write both directions to your mapping table when the initial order is created.

Definitely implement caching for your mapping table. Load it into memory when your integration service starts and refresh periodically or use event-based invalidation when new batches are created. For hundreds of updates per hour, an in-memory cache with hash lookup will have negligible performance impact. Just make sure your cache invalidation strategy handles new batch creations properly - when SAP creates a new production order with a new batch, that mapping needs to be immediately available for MES updates.

We can’t change MES’s internal batch ID format due to constraints with their database schema - it’s a legacy system. The mapping table idea makes sense, but I’m concerned about performance if we’re looking up mappings for every order update. We process hundreds of order status updates per hour. Would caching the mapping table in the middleware help?

I agree with maintaining a mapping table. However, there’s another consideration - batch ID format differences often indicate that you’re not using a consistent master data management approach. Ideally, one system should be the master for batch IDs and the other should adapt. If SAP is your system of record, MES should store and use SAP’s batch ID format internally, even if it displays differently in the UI. This eliminates the need for constant back-and-forth transformation and reduces the risk of mapping errors during updates.

The issue is likely that your mapping logic only works one direction (SAP to MES). For the reverse sync, you need to maintain a mapping table that stores both SAP’s batch ID format and MES’s numeric format. When MES sends updates back, your middleware should look up the SAP format using the MES numeric ID before forwarding to SAP.