Production planning API BOM explosion queries degrade performance during MRP run

Our external planning system queries the Production Planning API to retrieve BOM explosions for manufactured parts, but performance degrades severely during MRP runs. What normally takes 2-3 seconds per BOM can spike to 45-60 seconds when MRP is processing.

Current query pattern:


GET /API_PRODUCT_BOM_SRV/A_ProductBOM('MAT-FG-001')
  ?$expand=to_BOMItem/to_BOMSubItem,to_BOMItem/to_ComponentAllocation

We’re retrieving multi-level BOMs (up to 8 levels deep) with all component allocations. The query uses nested $expand which might be causing the performance hit. I haven’t explored selective $expand usage, query caching, or batch processing options yet. The BOM hierarchy optimization also seems like it could help, but I’m not sure how to implement it effectively. Should we be caching BOM structures or restructuring our queries to avoid the nested expansion during high-load periods?

Your performance degradation during MRP runs is caused by database contention and inefficient query patterns. Here’s a comprehensive optimization strategy that addresses all four focus areas:

1. BOM Hierarchy Optimization

Restructure how you retrieve multi-level BOMs to avoid deep nesting:

Instead of:


GET /API_PRODUCT_BOM_SRV/A_ProductBOM('MAT-FG-001')
  ?$expand=to_BOMItem/to_BOMSubItem/to_BOMSubItem/to_BOMSubItem

Use an iterative approach:


// Level 1: Get top-level BOM
GET /A_ProductBOM('MAT-FG-001')?$expand=to_BOMItem

// Level 2+: Fetch children only for assemblies
GET /A_BOMItem?$filter=ParentMaterial eq 'MAT-FG-001'
  and ItemCategory eq 'L'&$expand=to_BOMSubItem

This reduces query complexity from O(n^8) to O(n) for 8-level BOMs. Process levels sequentially, fetching only assembly components that need further explosion.

In your BOM master data (transaction CS02), consider:

  • Consolidating phantom assemblies where appropriate
  • Limiting BOM depth to 5-6 levels maximum
  • Using BOM variants for configuration differences instead of alternative BOMs

2. Selective $expand Usage

Be strategic about what you expand and when:


GET /A_ProductBOM('MAT-FG-001')
  ?$expand=to_BOMItem($select=Material,ComponentQuantity,ComponentUnit;
    $filter=ItemCategory ne 'T' and ValidityStartDate le datetime'2025-06-19'
  )
  &$select=BOMHeaderUUID,Material,BOMVersion

Key optimizations:

  • Use $select to retrieve only needed fields (Material, Quantity, Unit)
  • Filter out text items (ItemCategory=‘T’) and expired components
  • Avoid expanding ComponentAllocation unless you need warehouse-specific data
  • For planning purposes, you rarely need all component attributes

3. Query Caching Strategy

Implement a three-tier caching approach:

Tier 1: Static BOM Cache (24-hour TTL)

  • Cache complete BOM explosions for high-runner finished goods
  • Store in Redis or similar with key structure: BOM:{Material}:{Version}
  • Refresh daily or when ECM change notifications received
  • Serves 80% of queries during MRP runs without API calls

Tier 2: Session Cache (MRP run duration)

  • During an MRP run, cache all retrieved BOMs in memory
  • Clear cache when MRP completes
  • Prevents duplicate API calls for same material within one planning cycle

Tier 3: Partial Result Cache (1-hour TTL)

  • Cache individual BOM levels separately
  • Key structure: BOM:{Material}:Level{N}
  • Allows reuse of common sub-assemblies across different finished goods

Implementation pattern:


// Pseudocode for cached BOM retrieval:
1. Check Tier 1 cache for complete BOM explosion
2. If hit: return cached structure
3. If miss: check Tier 3 for individual levels
4. Fetch missing levels via API with selective $expand
5. Assemble complete BOM from cached + fetched levels
6. Store in Tier 1 and Tier 2 caches

4. Batch Processing

Group BOM retrievals into batch requests to reduce HTTP overhead:


POST /API_PRODUCT_BOM_SRV/$batch
Content-Type: multipart/mixed;boundary=batch_boundary

--batch_boundary
Content-Type: application/http

GET A_ProductBOM('MAT-FG-001')?$expand=to_BOMItem HTTP/1.1

--batch_boundary
Content-Type: application/http

GET A_ProductBOM('MAT-FG-002')?$expand=to_BOMItem HTTP/1.1

--batch_boundary
Content-Type: application/http

GET A_ProductBOM('MAT-FG-003')?$expand=to_BOMItem HTTP/1.1

--batch_boundary--

Batch 25-30 BOM queries per request. This:

  • Reduces connection overhead from 200 HTTP requests to 8-10 batch requests
  • Allows SAP to optimize database access patterns
  • Maintains transaction consistency across related BOMs

MRP-Specific Optimization:

During MRP runs, database contention is highest. Implement these strategies:

a) Pre-fetch BOMs before MRP: Run a background job 30 minutes before scheduled MRP to populate your cache with all active finished goods BOMs

b) Parallel processing with rate limiting:

  • Process BOMs in parallel threads (4-6 threads)
  • Implement rate limiting: max 10 API calls per second
  • This balances throughput with system load

c) Delta processing:

  • Track which finished goods have engineering changes
  • During MRP, only fetch BOMs that changed or weren’t cached
  • Serve unchanged BOMs from cache

Monitoring and Tuning:

Track these metrics:

  • Cache hit rate (target: >85% during MRP)
  • Average API response time (target: <3s per BOM)
  • P95 response time (target: <8s)
  • Total BOM retrieval time per MRP run

If performance is still poor after these optimizations:

  • Check SAP system load during MRP (transaction ST03N)
  • Verify database statistics are current (transaction DB02)
  • Consider scheduling MRP runs during off-peak hours
  • Evaluate if BOM data can be replicated to external planning system

By combining hierarchy optimization (reduces query complexity), selective expansion (minimizes data transfer), intelligent caching (eliminates redundant calls), and batch processing (reduces overhead), you should see API response times drop from 45-60s to under 3-5s even during peak MRP runs. The caching strategy alone typically reduces API load by 85-90%, which is critical during high-contention periods.


This draft is based on general SAP S/4HANA knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

Your nested $expand is killing performance. Each level multiplies the database joins, and 8 levels deep means exponential query complexity. Flatten your query structure - fetch the top-level BOM first, then make separate calls for sub-items only when needed.

Implement selective $expand based on what you actually need. If you only need certain BOM levels or specific component attributes, use $select to limit fields and $filter to restrict which sub-items are expanded. For example, exclude phantom items or components with zero quantity if they’re not relevant to your planning calculations. This can reduce payload size by 60-70% and significantly improve response times.

BOM structures are relatively static compared to inventory or order data. Implement a caching layer in your external system. Cache the complete BOM explosion for each finished good and refresh it only when engineering changes occur (ECM notifications). During MRP runs, serve from cache instead of hitting the API repeatedly. We reduced API calls by 95% using this approach with a 24-hour cache TTL.

Check if your BOM structure in SAP is optimized. Transaction CS02 shows the BOM hierarchy - look for unnecessary phantom assemblies or overly deep nesting that could be flattened. Sometimes engineering creates complex structures that aren’t needed for planning purposes. Also verify that alternative BOMs and BOM variants are properly configured so your API isn’t retrieving all alternatives when you only need the primary.

Use the batch API to retrieve multiple BOMs in a single request. Instead of making sequential calls for each finished good, group them into batches of 20-30 and use $batch processing. This reduces HTTP overhead and allows SAP to optimize the database queries internally. We cut our total API processing time from 15 minutes to under 3 minutes for 200 finished goods.

Tested this on S/4HANA 2023 FPS01 with a 15,000-component BOM structure, and replacing deep $expand nesting with iterative A_ProductBOM API calls cut MRP runtime by 40%.