Skip to content
VenSoc Technologies

What actually breaks when you write to SAP over OData

The integration is rarely the hard part. The hard part is that master data in a system of record is effectively permanent, and a network retry is not.

Muhammad Omar7 min read

In short

Writing to SAP over OData fails in four predictable places: an assumed field contract that does not match the service metadata, a multi-level payload sent as separate calls instead of a deep insert, duplicate detection that only checks what is already in SAP, and a retry that creates a second record because the interface has no update path.

Why is material master data worth this much effort?

Material master records are the foundational data that every downstream process reads. Procurement, production, costing and inventory valuation all depend on them. A wrong unit of measure or a wrong conversion factor does not fail loudly — it produces quietly wrong numbers in four different reports, and by the time somebody notices, months of transactions have been posted against it.

The property that changes the engineering is permanence. Where an interface creates records and has no update or delete path, every record it writes is effectively permanent from the moment it lands. Unwinding a bad record is not a delete; it is a correction process involving people, and it is expensive.

That single fact should drive the entire design. A system writing permanent records into a system of record needs the validation, the approval path and the audit trail in front of the write, not error handling behind it. Most integration projects invert this, treat the write as the deliverable, and discover the governance requirement after the first bad batch.

Why should I verify the field contract against $metadata?

Because the specification you were given and the service that is actually deployed are different artefacts, and only one of them is authoritative.

An OData V2 service exposes its own contract at the `$metadata` endpoint: entity types, property names, types, nullability and navigation properties. Reading it takes minutes. Assuming the field list from a spreadsheet a functional consultant sent last quarter takes no time at all and is how an integration ships against fields that were renamed, retyped, or never existed.

The class of defect this catches is worth naming, because it is not the one people expect. It is not a missing field, which fails loudly. It is a field whose type or permitted values differ from what the source data assumes — a unit conversion that is structurally invalid, say — which the file format accepts happily and the target system either rejects at posting time or, worse, stores in a form nobody notices is wrong.

This is a specific instance of a general rule VenSoc applies to every integration: no identifier is used before it has been read at its source. Not the column name, not the type, not the nullability. Pattern-matching a field name from a sibling entity produces code that compiles, reads correctly, and fails against a system nobody can quickly change.

Authoritative source
The service’s own $metadata document
Not authoritative
A field list in a spreadsheet or a slide
What verification catches
Renamed fields, wrong types, invalid conversion factors, phantom columns
Cost of verifying
Minutes, once, per entity

When do I need a deep insert rather than separate calls?

Whenever the thing you are creating is a parent with children that must exist together. In OData V2 a deep insert posts the parent and its related entities in a single request, and SAP processes them as one unit of work.

The alternative — creating the parent, then looping over the children with separate calls — looks simpler and introduces a failure mode with no clean recovery. If the third of five child calls fails, the parent now exists in SAP in a partial state. There is no transaction to roll back, and if the interface has no delete path, there is no way to remove what was created. You are left with a half-built permanent record.

A deep insert removes that entire class of failure. It also removes a category of ordering bug, because you are no longer responsible for sequencing dependent creates correctly across a network that can reorder or drop anything.

The cost is that payloads get large and error messages get less specific: a deep insert that fails tells you the unit failed, not which child caused it. That is a debugging cost worth paying, and it is mitigated by validating the whole structure before you send it rather than discovering problems from SAP’s response.

Why is duplicate detection harder than checking SAP?

Because by the time a duplicate reaches SAP, checking SAP is too late. The check has to happen across every surface where a duplicate can originate, and there are more of those than teams expect.

A governed pipeline needs to check at least four. Against records already approved and posted, which is the obvious one. Against submissions currently in flight, awaiting approval — two requesters can independently submit the same material on the same morning. Against other rows within the same uploaded file, because a spreadsheet assembled by three people routinely contains internal duplicates. And against previously rejected requests, so that a material rejected for a good reason last month does not quietly reappear.

The in-file case is the one most designs miss, and it is the most common in practice. Validation that treats each row independently will happily approve two identical rows in the same upload.

Matching also needs to run on more than the primary key, because the whole problem is that duplicates do not share one. Matching on each of several identifying fields independently, and flagging a clash on any of them for human review, catches near-duplicates that an exact-match check waves through.

What happens when the network drops mid-write?

This is the question that separates an integration that survives production from one that works in a demo. The client sends a create, the connection drops, and the client does not know whether SAP processed it.

The naive retry creates a second permanent record. On an interface with no update or delete path, that duplicate is now a manual correction — exactly the outcome the entire governance layer was built to prevent, reintroduced by the transport layer.

The mechanism that fixes it is a create-only re-send guard: the system records that a specific request was dispatched, and a retry of that same logical request can never produce a second create. It either confirms the original landed or reports honestly that the outcome is unknown and needs a human. An interface that cannot update cannot be made idempotent by SAP, so idempotency has to be enforced on the sending side.

The general principle applies well beyond SAP. Any time you write to a system that cannot delete, retry semantics are a first-class design decision and not an error-handling detail to be added later.

What does the security boundary look like?

An integration that writes to a system of record is a high-value target, and the controls are unglamorous.

Credentials never reach the browser. The session is server-side and CSRF-protected, roles are strictly separated so that a requester cannot approve their own submission, and every action — submit, amend, approve, reject, dispatch — is written to an immutable audit trail. When somebody asks in eighteen months why a material exists, the answer is a record, not a recollection.

On the network side, SAP systems are typically reachable only from known addresses. That means a static egress IP, which in a serverless deployment is not free: it needs a VPC connector and a NAT gateway to give ephemeral containers a stable outbound address. TLS to the SAP endpoint should be pinned rather than left to default trust.

None of this is exotic. It is listed because integration projects routinely treat it as infrastructure work to be scheduled later, and it is not — the separation of duties and the audit trail are the product. Without them you have built a faster way to put unreviewed data into a system that cannot forget it.

Common questions

Is OData the right choice, or should we use IDoc?
It depends on whether you need a response. OData gives synchronous request-response, which suits an approval workflow where a requester waits for confirmation. IDoc is asynchronous and better suited to high-volume batch exchange where immediate confirmation is not required. Many landscapes need both.
Can this be done without a middleware platform?
Yes. A well-structured application service can call OData directly. Middleware earns its place when many systems need the same transformations, when guaranteed delivery and replay are required, or when an integration team owns the layer. For a single governed workflow it is often overhead.
How long does an integration like this take?
The write itself is days. The governance around it — validation rules, approval routing, duplicate detection, audit trail, retry semantics — is where the time goes, and it is proportional to how much the business rules have been written down before you start. Undocumented rules are the schedule risk.
What if our SAP team cannot expose a service?
That is a common constraint and it is usually organisational rather than technical. The workable path is to scope the smallest service that satisfies the use case, agree the contract in writing, and verify it against $metadata once deployed. Designing against a service that has not been agreed is how integration projects stall.

Topics

  • SAP integration
  • OData
  • ERP
  • Master data governance

Where VenSoc applies this

  • SAP & ERP integration

    VenSoc builds integration middleware between SAP and the systems around it — commerce platforms, warehouse systems, CRMs and custom applications. Work covers S/4HANA, SAP Business One and SAP BTP, using IDoc, OData and REST interfaces with an intermediate queue rather than direct point-to-point calls.

  • Data platform engineering

    VenSoc builds the ingestion pipelines, warehouse models and governance layer that applied AI work depends on. Most organisations discover this gap at the point their first AI initiative needs reliable, joined, documented data — and finds it distributed across systems that disagree with each other.

More from Field Notes

Want this applied to your system rather than described?

The technical review is ninety minutes and produces a written assessment you keep either way.

Book a technical review