Zum Inhalt springen

Schlüssel und Schreibhoheit

Auch in 19 Sprachen

English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · 简体中文 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Українська · Español (México) · Français (Canada)

A semi-detached house with each half painted a different colour, blue and cream, meeting in a straight line down the middle.
Mit KI erstelltes Bild

Modul 2 von 4 im Kapitel Integration und Datenbewegung, Kapitel 9 des Kurses Data Architect. Jedes Modul steht für sich. Previous: Before the Arrow · Next: Proof of Delivery ⟲

Die Frage, die dieses Modul beantwortet: Wie bleiben Datensätze zugeordnet, und wer darf was ändern?

Every time an integration touches a record, it has to answer two questions: which record is this? and whose value is this? Get the first wrong and you create duplicates or update the wrong record. Get the second wrong and you overwrite data someone else owns. These aren’t edge cases. They’re two of the most common ways integrations damage a good data architecture. ⟲

In chapter 6 we drew the most common integration I see: one Salesforce and one ERP. Customers and products come in from the ERP; orders and order items go out from Salesforce. Several flows, in order. ⟲

Salesforce and the ERP: several flows, in order Salesforce on the left, the ERP on the right (SAP, Oracle or another). Salesforce has Account, Opportunity, Opportunity Product and Product; the ERP has Customer (the golden record), Order, Order Item and Product (the SKU). First, what the ERP owns comes in: customers into Account, daily or maybe hourly, and products into Product, daily or sooner. Then what Salesforce creates goes out: opportunities as orders, and opportunity products as order items, near real time, for customers and products the ERP already knows. Underneath: the ERP's customers and products come in first; only then can orders go out; one flow alone should worry you. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.44.0", "built": "2026-10-27", "id": "DGM-DA-MD-55", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.2.0", "theme": "stevetecharc 1.4.0"} SALESFORCE THE ERP (SAP, ORACLE OR ANOTHER) Account the customer Opportunity what's being sold Opportunity Product a line: product, quantity, price Product with its price book entries Customer the golden record Order for a customer it knows Order Item for a product it knows Product the SKU customers in: daily, maybe hourly products in: daily, or sooner orders out: near real time order items out: near real time The ERP's customers and products come in first; only then can orders go out. One flow alone should worry you. © 2026 Twinshark LLC · stevetecharc.com
Zum Vergrössern klicken

From chapter 6: Salesforce and the ERP, several flows in order. ⟲

Now zoom in on the first arrow: customers into Account. Every record that crosses it asks both questions. Which account is this customer? And which of its fields may the ERP write? ⟲

The ERP sends a customer: Steve’s Plumbing, payment terms Net 30. Which account? Search by name? Then you meet Steve’s Plumbing, Steve’s Plumbing LLC, Steve’s Plumbing - West, and a Steve’s Plumbing & Heating that has nothing to do with it. Everyone knows the first two are the same company, and the integration doesn’t. Names are useful to people and terrible as integration keys. The integration needs a stable identity. ⟲

So when a Salesforce record corresponds one-to-one with a record in a significant external system, carry that system’s key on the Salesforce record, in a field marked External ID. The ERP’s customer number 10442 lives on the account. Now the ERP’s updates don’t need guessing. ⟲

And an External ID can drive upsert: one call that decides for you. If the key isn’t found, the record is created (unless the call says update only). If it’s found once, that record is updated. If it’s found more than once, the call fails with an error and nothing is created or updated (Insert or Update (Upsert) a Record Using an External ID (öffnet in einem neuen Tab), REST API Developer Guide, checked 2026-10-27). That makes integrations far easier to restart safely. ⟲

That last rule is why I mark the field Unique as well. External ID says this field holds another system’s identifier and can be used for matching. Unique says two records may never share the value (Custom Field Attributes (öffnet in einem neuen Tab), Salesforce Help, checked 2026-10-27). If the architecture depends on one-to-one identity, I’d rather hit the conflict the moment someone creates a second account with 10442 than discover it as an integration mystery six months later. ⟲

Test knowledge. Upsert matches on an External ID field: no match creates a record, one match updates it, more than one match fails without changing anything. Marking the External ID field Unique stops the duplicates that cause that failure. An object can have up to 25 External ID fields, and fields marked Unique count toward that limit. ⟲

First: is the relationship really one-to-one? One Salesforce record for one external record, and back. If one ERP customer maps to three Salesforce accounts, or three ERP customers legitimately map to one account because Salesforce models the parent differently, the External ID can’t be a one-to-one key. Don’t force a complicated relationship into a field because External IDs are convenient; design a different identity. ⟲

Second: does the field hold one system’s key, with one meaning? If a field sometimes holds the ERP’s number and sometimes a partner’s, whose number is 847291? The field no longer says what its value means. One key field, one meaning. ⟲

Then the company opens an office in Munich, and the European ERP creates its own customer record for Steve’s Plumbing: customer 88310. Same company, two ERP records, two keys. They can’t both live in one External ID field on one account. ⟲

The answer is the rule from chapter 6: add records, not fields. Give each ERP record its own Salesforce record, one-to-one: child accounts under a parent, peer accounts, or one account with a child object per ERP. Which one depends on how much of the ERP structure sales should see, and on how well the client keeps its own ERPs in sync. ⟲

One customer, two ERPs: three ways, and one not to use One customer, Steve's Plumbing, held in two ERPs: ERP North America as customer 10442 and ERP EMEA as customer 88310, on the right. On the left, Salesforce, four ways. First, an account hierarchy: two child accounts, Steve's Plumbing - North America and Steve's Plumbing - EMEA, each keyed one-to-one to its ERP's customer, each pointing to the parent account, Steve's Plumbing. Second, peer accounts: the parent is gone, and Steve's Plumbing - North America and Steve's Plumbing - EMEA stand side by side, each with its region and keyed to its ERP. Third, a child object: one Steve's Plumbing account that sales sees, and two child records, ERP Customer - North America with ERP key 10442 and ERP Customer - EMEA with ERP key 88310, each keyed to its ERP and each pointing to the one account. Last, in coral and marked "not this": one account with a key field for each ERP, NA_ERP_ID__c, EMEA_ERP_ID__c and one more for every new ERP, with both ERPs pointing at it. Underneath: add records, not fields; each ERP record gets its own Salesforce record, never its own key field on one record; the same three ways work when the ERPs split by function, plumbing and electrical. SALESFORCE TWO ERPS ERP North America customer 10442 ERP EMEA customer 88310 Steve's Plumbing the one account sales sees ERP Customer - North America a child record · ERP key 10442 ERP Customer - EMEA a child record · ERP key 88310 key 10442 key 88310 child of child of Add records, not fields: each ERP record gets its own Salesforce record, never its own key field on one record. The same three ways work when the ERPs split by function, plumbing and electrical. HOW TO READ IT the customer as sales sees it the anti-pattern: a key field for every ERP © 2026 Twinshark LLC · stevetecharc.com
Zum Vergrössern klicken

One of the three ways: a child object per ERP record. All three, and the costs of each, are in chapter 6: One Customer, Two ERPs. ⟲

What I don’t want is the fourth answer: one account with a key field for each ERP, NA_ERP_ID__c, EMEA_ERP_ID__c, and another every time the company buys a business. That’s an anti-pattern I don’t like. It hides repeating structure in fields, makes every new ERP a schema change, and spends the object’s allowance of External ID fields one acquisition at a time. Integrations make that mistake tempting, because each new arrow seems to need “its” field. It doesn’t. It needs its record. ⟲

Steve Trucking: One Field, the Source in the Value

Abschnitt betitelt „Steve Trucking: One Field, the Source in the Value“

Now our own landscape. Back in module 1 we zoomed in on Redrock’s manifests: about 1,100 deliveries a day, each one becoming a Work Order. At Checkpoint 1 we gave every Work Order one External ID field, unique, holding the partner’s own order and delivery reference with the partner named in the value. ⟲

One key field, the source in the value Salesforce's Work Orders on the left, the Retail Partners on the right. Redrock's delivery 8472914, Keystone's Phoenix delivery 8843119 and Brightwave's delivery 778120 each upsert into a Work Order by its key, held in one field, Partner_Delivery_Key__c: REDROCK-8472914-1, KEYSTONE-PHX-8843119-1, BRIGHTWAVE-778120-1. Then a fourth partner, Oakline, joins, and its delivery 30017 upserts as OAKLINE-30017-1 in the same field, tagged "a new value, not a new field". Underneath: one External ID field, marked unique; the value names the partner; each Work Order comes from one partner, so one key is enough. SALESFORCE: WORK ORDERS RETAIL PARTNERS Work Order Partner_Delivery_Key__c = REDROCK-8472914-1 Work Order Partner_Delivery_Key__c = KEYSTONE-PHX-8843119-1 Work Order Partner_Delivery_Key__c = BRIGHTWAVE-778120-1 Redrock delivery 8472914, line 1 Keystone Phoenix DC, delivery 8843119, line 1 Brightwave delivery 778120, line 1 upsert by key upsert by key upsert by key One External ID field, marked unique; the value names the partner. Each Work Order comes from one partner, so one key is enough. © 2026 Twinshark LLC · stevetecharc.com
Zum Vergrössern klicken

One key field on every Work Order. The value says whose delivery it is. ⟲

Is that the same rule? Yes. A Work Order comes from exactly one partner, so each record has exactly one key from one source. The field’s meaning never changes: the Retail Partner’s delivery reference. And because the value names the partner, REDROCK-8472914-1 can never collide with a Keystone delivery that happens to have the same number. ⟲

Now the late change from the brief: a fourth partner, Oakline, wants to go live at three distribution centers in 90 days. ⟲

One key field, the source in the value Salesforce's Work Orders on the left, the Retail Partners on the right. Redrock's delivery 8472914, Keystone's Phoenix delivery 8843119 and Brightwave's delivery 778120 each upsert into a Work Order by its key, held in one field, Partner_Delivery_Key__c: REDROCK-8472914-1, KEYSTONE-PHX-8843119-1, BRIGHTWAVE-778120-1. Then a fourth partner, Oakline, joins, and its delivery 30017 upserts as OAKLINE-30017-1 in the same field, tagged "a new value, not a new field". Underneath: one External ID field, marked unique; the value names the partner; each Work Order comes from one partner, so one key is enough. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.45.0", "built": "2026-10-27", "id": "DGM-DA-DI-21", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.2.0", "theme": "stevetecharc 1.4.0"} SALESFORCE: WORK ORDERS RETAIL PARTNERS Work Order Partner_Delivery_Key__c = REDROCK-8472914-1 Work Order Partner_Delivery_Key__c = KEYSTONE-PHX-8843119-1 Work Order Partner_Delivery_Key__c = BRIGHTWAVE-778120-1 Work Order Partner_Delivery_Key__c = OAKLINE-30017-1 a new value, not a new field Redrock delivery 8472914, line 1 Keystone Phoenix DC, delivery 8843119, line 1 Brightwave delivery 778120, line 1 Oakline joins: delivery 30017, line 1 upsert by key upsert by key upsert by key upsert by key One External ID field, marked unique; the value names the partner. Each Work Order comes from one partner, so one key is enough. © 2026 Twinshark LLC · stevetecharc.com
Zum Vergrössern klicken

A new partner is new data, not a schema change. ⟲

With a key field per partner, Oakline would mean a new field, new matching logic and a deployment before the first manifest. With one field and the source in the value, it means a new prefix. The account and the Work Order end up following the same rule from different directions: one key per record. When one business thing has several external records, add records. When each record has one source, one field is enough, as long as the value says which source. ⟲

Remember the end of module 1. Tonight’s Redrock manifest timed out on its way into Salesforce, and the integration layer didn’t know whether anything had saved (And When It Fails). So it sent the manifest again. A blind insert would have created a second Work Order for every delivery that had already saved. An upsert on the partner’s key matches the existing records and creates only what’s missing. That’s the beginning of idempotency: repeating an operation shouldn’t keep creating extra effects. Module 3 goes further. Safe retries begin with keys. ⟲

The key tells Salesforce which customer. It doesn’t mean the ERP owns every field on the account. Identity and authority are different questions, which is why “the ERP syncs accounts to Salesforce” is a dangerous design. All fields? Some? Both directions? Which one wins? That isn’t a data architecture; it’s an argument waiting to happen. ⟲

When I teach this, I ask the room: what fields come over from SAP? Name, address, billing and shipping addresses, payment terms. Those are the ERP’s master data fields. Then: do we have the ability to add our own fields in Salesforce that we don’t send to SAP? Yes. A sales rating, the last order date, pretty much anything marketing related. So the account in Salesforce is a golden record that’s really a hybrid: the ERP is the system of record for some fields, Salesforce for others. ⟲

One record, two owners Three areas: people on the left, one account, Steve's Plumbing, in the middle, and the ERP on the right holding customer 10442, the golden record. The account is split by owner: the ERP's fields (legal name, addresses, payment terms) and Salesforce's fields (sales rating, last order date, marketing). First, the integration writes only the ERP's fields, and the sales team edits only Salesforce's. Then the sales team wants to change the payment terms from Net 30 to Net 45: it asks for a change, which becomes a change request, tagged "a request, not an edit", sent to the ERP, the owner. Underneath: the key says which record; authority says which fields; a change to the ERP's field is a request to the ERP, and its answer comes back through the integration. PEOPLE ONE ACCOUNT: STEVE'S PLUMBING THE ERP Sales team works the account every day The ERP's fields legal name, addresses, payment terms Salesforce's fields sales rating, last order date, marketing ERP customer 10442: the golden record integration writes sales edits The key says which record. Authority says which fields. A change to the ERP's field is a request to the ERP; its answer comes back through the integration. HOW TO READ IT the ERP owns these fields and writes them Salesforce owns these fields © 2026 Twinshark LLC · stevetecharc.com
Zum Vergrössern klicken

One record, two owners. The integration writes the ERP’s fields; sales edits Salesforce’s. ⟲

That’s chapter 6’s rule, authority is assigned attribute by attribute (Truth Per Attribute), made executable. The rule isn’t “the ERP can update Account.” It’s “the ERP can update the fields the ERP owns.” A much stronger contract. ⟲

And protect it in the org, not just in a document. A common construct I’ve seen across implementations: separate the ERP’s accounts by record type, and let only the integration create them. Salespeople create and edit their own sales accounts; the ERP’s customer accounts come in through the integration, with the ERP’s fields read-only on the page layout (A Record Type for Each Flow). ⟲

Test knowledge. Write authority is enforced in the org, not only in the integration. Expect to separate integration-owned records by record type, make integration-owned fields read-only for users with page layouts and field-level security, and give the integration user only the access its contract needs. ⟲

Wenn Salesforce ein Feld ändern will, das dem ERP gehört

Abschnitt betitelt „Wenn Salesforce ein Feld ändern will, das dem ERP gehört “

A rep needs the payment terms changed. The ERP owns them. Bad answer one: let Salesforce change them locally until the ERP overwrites them. The user’s change appears to succeed, then mysteriously vanishes. Bad answer two: let both systems write them and the last write wins. That’s not mastering; that’s a race condition. ⟲

If the ERP owns the field, a change from Salesforce is a request to the authoritative system. Sometimes the ERP even owns creation: you can’t just create the account, you submit a request through an API, and the ERP creates it. ⟲

One record, two owners Three areas: people on the left, one account, Steve's Plumbing, in the middle, and the ERP on the right holding customer 10442, the golden record. The account is split by owner: the ERP's fields (legal name, addresses, payment terms) and Salesforce's fields (sales rating, last order date, marketing). First, the integration writes only the ERP's fields, and the sales team edits only Salesforce's. Then the sales team wants to change the payment terms from Net 30 to Net 45: it asks for a change, which becomes a change request, tagged "a request, not an edit", sent to the ERP, the owner. Underneath: the key says which record; authority says which fields; a change to the ERP's field is a request to the ERP, and its answer comes back through the integration. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.45.0", "built": "2026-10-27", "id": "DGM-DA-DI-22", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.2.0", "theme": "stevetecharc 1.4.0"} PEOPLE ONE ACCOUNT: STEVE'S PLUMBING THE ERP Sales team works the account every day The ERP's fields legal name, addresses, payment terms Salesforce's fields sales rating, last order date, marketing Change request payment terms: Net 30 to Net 45 a request, not an edit ERP customer 10442: the golden record integration writes sales edits asks for a change sent to the owner The key says which record. Authority says which fields. A change to the ERP's field is a request to the ERP; its answer comes back through the integration. HOW TO READ IT the ERP owns these fields and writes them Salesforce owns these fields © 2026 Twinshark LLC · stevetecharc.com
Zum Vergrössern klicken

A request, not an edit. The ERP accepts or rejects it, and its answer comes back through the integration. ⟲

The ERP accepts or rejects it, and the authoritative value comes back down the same arrow it always does (When Authority Is Shared). Integration is where that authority model becomes real. ⟲

“We need a bidirectional integration.” Fine, but that doesn’t tell me enough. Data can move both ways while every field still has one owner. Look at Steve Trucking’s Redrock arrows: the manifest comes in, and Redrock owns what was ordered and where it goes; status goes back out, and Salesforce owns the appointment, the crew and the delivery status. Two-way movement, clear authority, very different from “both systems can update everything.” Bidirectional movement doesn’t require bidirectional authority. ⟲

And when both systems really can write the same field, you get the loop: Salesforce changes the phone number, sends it to the ERP, the ERP sees a change and sends it back, Salesforce sees a change… Good integration design tells a real business change from the echo of one it just sent, and there are several technical ways to do it. But the data architect should see the root cause: write authority and change provenance aren’t clear enough. The cleaner the authority model, the fewer loops you have to engineer around. ⟲

Machen Sie Autorität sichtbar, und fragen Sie, warum Sie kopieren

Abschnitt betitelt „Machen Sie Autorität sichtbar, und fragen Sie, warum Sie kopieren “

Deshalb mag ich Namen, die zeigen, wem extern geführte Daten gehören: Manchmal ist ERP_Credit_Status__c besser als Credit_Status__c, weil das Feld selbst sagt: „Das kommt aus dem ERP.“ Nicht jedes integrierte Feld braucht ein Präfix; urteilen Sie selbst. Aber wenn Autorität zählt, sollte künftiges Entwicklungspersonal kein 90-seitiges Architekturdokument brauchen, um zu lernen: „Das nicht aktualisieren, das gehört dem ERP.“ Das Modell sollte es sagen.

Und wenn dem ERP der Kreditstatus gehört, braucht Salesforce überhaupt eine Kopie? Vielleicht: wenn Menschen ihn ständig brauchen, Automatisierung von ihm abhängt, Berichte ihn nutzen und die nötige Aktualität erreichbar ist. Aber jede Kopie ist eine Synchronisierungsverantwortung. Wenn Salesforce den Wert nur gelegentlich braucht und er immer aktuell sein muss, kann es besser sein, ihn an der Quelle abzurufen; das ist Virtualisierung, in Teil 3. Die Frage lautet nicht „Können wir das Feld integrieren?“ Sie lautet „Warum kopieren wir es?“

External identifiers aren’t always permanent. Systems merge customers, organizations consolidate, an acquired company brings its own ERP, legacy IDs are retired, records get new numbers in a conversion. For each important cross-system key: who assigns it, when, can it change, can it be reused, what happens in a merger or a migration, and do we keep the old ID for traceability? When a company buys a business that runs its own ERP, the answer is a new record per ERP record, not a new field. A key is part of the data lifecycle. ⟲

Dasselbe gilt zwischen Salesforce-Orgs. Nach einer Übernahme gibt es Org A und Org B: Eine Datensatz-ID aus Org A bedeutet etwas in Org A. Sie ist nicht automatisch der Unternehmensschlüssel. Wenn Org B dieselbe geschäftliche Entität zuordnen muss, brauchen Sie trotzdem eine bewusste Strategie für systemübergreifende Identität. Zwei Salesforce-Orgs sind dafür zwei Systeme.

A nightly job sets out to send 20,000 customer updates and fails at 12,417. Tomorrow, what? Start over? Continue? Which already succeeded? With stable keys and safe upserts, you have options: retry, restart, reconcile, detect duplicates, compare source and target, prove completeness. Without them, recovery gets hard fast. Identity isn’t just a modeling concern. It’s operational reliability. ⟲

Beyond the exam: what AI changes. “Agent, update the customer.” Which customer, by what key, and update what: everything it can technically reach? An agent is another integration client. Its actions need explicit keys and narrow write contracts: resolve the right identity, respect the authoritative source, write only the fields that action may write, turn changes to another system’s fields into requests, keep provenance, and don’t turn retries into duplicates. Autonomy makes those controls more important, not less. ⟲

  • Which stable key identifies the same business record across each significant system boundary, and whether the relationship is truly one-to-one. ⟲
  • When one business thing has several external records, which records represent them: a hierarchy, peers or a child object, never a key field per system. ⟲
  • Which system owns each important attribute, and so which integration may write it, enforced with record types, page layouts and field-level security. ⟲
  • How a change to a field another system owns becomes a request to that system. ⟲
  • Wie Bewegung in beide Richtungen die Autorität klar hält, statt zu „der letzte Schreibvorgang gewinnt“ zu werden.
  • Ob extern geführte Daten überhaupt kopiert werden sollten und wie dieselben Regeln für Agenten und andere Salesforce-Orgs gelten.

Every integration write has to answer which record? and whose value? The key answers the first; the authority model the second. So don’t settle for “the ERP syncs accounts.” Tell me how the ERP identifies the account, which key we store and on which record, whether it’s really one-to-one, which fields each system owns, what happens when Salesforce wants to change an ERP value, and what happens on retry. Know the record. Know the owner. Then let the integration write. ⟲