画箭头之前
另有 19 种语言版本
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) · Deutsch (Schweiz)

第 1 个模块,共 4 个,属于 Data Architect 课程第 9 章集成与数据流动。每个模块都可以单独阅读。 上一篇:上一章查询与检索架构 · 下一篇:键与写入归属
The question this module answers: What must a data architect know about an integration before anyone draws the arrow? ⟲
Start With the Picture
Section titled “Start With the Picture”Here’s Steve Trucking at the end of Part 1. At Checkpoint 1 I drew what I would architect: the partners’ manifests coming in, status going back out, the latest truck position from FleetLink, status events to Snowflake, delivery counts to the finance ERP. And in the middle of all those arrows, I drew a box and wrote on it: Integration, designed in Part 2. ⟲
This is Part 2. ⟲
Checkpoint 1’s landscape. Every arrow on it is a decision about data; this module zooms in on one. ⟲
I love system landscapes. Even two boxes protect you: put one up on a first call and you’d be surprised how many memories are suddenly jogged. “Wait, where’s my mobile app? Where’s the push of my orders?” But a landscape has a weakness, and it’s the arrows. Look at this one. Every arrow is the same thin line. One of them might carry one record every few minutes, another 500 a minute, another a nightly file of 200,000. One is a request where Salesforce waits for an answer; another is an event Salesforce publishes and forgets. Those aren’t the same architecture. The picture doesn’t show the difference. So before I draw an arrow, I want to know what it means. ⟲
That’s what before the arrow means: the data questions you answer before anyone chooses REST, events, files or middleware. ⟲
“那是集成架构师的事”
Section titled ““那是集成架构师的事” ”Maybe. On a large program, someone else may design the APIs, events, transformations and middleware. That’s fine. This chapter is a sampler plate; the Integration Architect course is the full meal. But I absolutely want to know what the integration architect is planning, because the integration is about to touch my data. An API pushing hundreds of records a minute is a different data problem from an hourly bulk load. Those writes can fire automation, recalculate sharing, lock parent records, run duplicate checks and validation, update roll-ups, grow storage and trigger other integrations. The data architect doesn’t have to build the integration, but decides what it’s allowed to do to the data. Understand the traffic that’s coming. ⟲
Zoom In on One Arrow
Section titled “Zoom In on One Arrow”So let’s pick one arrow and look closely: Redrock’s manifests, coming in through the integration layer and landing in Salesforce. In chapter 4 we zoomed in on an arrow too, and saw the plumbing: where the server listens, how the client authenticates, the protocol and the payload. That’s the integration architect’s view. Here’s the data architect’s view of the same kind of arrow: seven questions, and what each answer does to the data. ⟲
One arrow, seven questions. None of the answers names a technology. ⟲
Read down the left column. Redrock starts it. The manifests move from Redrock to Salesforce. They’re sent a day or two ahead, but revised on the day. About 1,100 deliveries a day arrive as a set per distribution center each evening, then as single revisions. Redrock’s order and delivery reference identifies each one. Redrock owns what was ordered and where it goes. And Redrock, as the client, is the one that sees whether the call worked. ⟲
Now the right column, which is where the data architect lives. A resent manifest must update, not duplicate. Redrock may change the items and the address, but not the crew. A coordinator must see a revision before the truck leaves the dock. About 350,000 Work Orders a year come down this one arrow, growing 30% a year. Notice what isn’t in either column: REST, Bulk API, platform events, MuleSoft. Choose the mechanism before you understand the movement, and you’re designing backwards. ⟲
The seven questions, for every important arrow: ⟲
- Who starts it? ⟲
- Which way does the data move? ⟲
- 它需要多新?
- 有多少数据,是什么形状?
- What’s the key? ⟲
- 谁可以写入哪些字段?
- 谁知道它是否成功了,失败时谁负责恢复?
This module works through the first four, plus what an arrow costs. Module 2 takes the key and the write authority; module 3 takes the last question. ⟲
谁发起,不等于数据往哪里走
Section titled “谁发起,不等于数据往哪里走 ”What does an arrow on a landscape mean? Ask a room and you get two answers. One: who’s the client and who’s the server, who opens the connection. Two: which way the data flows. Both are fair, and they can point in completely opposite directions. A user connects to Salesforce and a sea of data flows back the other way. So you have to decide what your arrows mean. I draw mine from the system that opens the connection, and I put what moves, and which way, in the label. That’s the rule on every landscape in this course. ⟲
Take FleetLink. At Checkpoint 1 we decided Salesforce keeps only each truck’s latest position. That data moves one way: FleetLink to Salesforce. But who starts it? Two designs: ⟲
- Salesforce asks. Every few minutes a scheduled job in Salesforce calls FleetLink: “Where are my trucks?” Salesforce is the client. The data still flows FleetLink → Salesforce. ⟲
- FleetLink tells. Whenever a truck moves far enough, FleetLink calls into Salesforce with the new position. FleetLink is the client. The data still flows FleetLink → Salesforce. ⟲
Same data, same direction, different initiator. And it matters, because the initiator carries the load and the responsibility. In the first design, Salesforce spends its own limits making calls, holds FleetLink’s credentials, and has to handle FleetLink being down. In the second, FleetLink spends Salesforce’s API calls, and FleetLink has to notice when Salesforce rejects something. In class I call this the direction of action: who’s starting the action, which can be different from the data flow. ⟲
Salesforce asks. Salesforce starts it; the positions flow FleetLink → Salesforce. ⟲
FleetLink tells. FleetLink starts it; the positions still flow FleetLink → Salesforce. ⟲
At its simplest, it’s still client and server. The client starts the conversation and the server listens. The server knows whether it received, rejected, processed or failed the request. What it can’t see is whether its response made it back. The client can. Only the client sees the whole round trip. That has a big consequence for recovery, which module 3 makes concrete. ⟲
Test knowledge. Separate who initiates an integration from which way the data flows. “Salesforce calls the ERP to get the credit status” is Salesforce-initiated, but the data flows from the ERP into Salesforce. Expect scenarios that describe one and ask about the other. ⟲
它需要多新?
Section titled “它需要多新? ”The first word I challenge is “real time.” Why? What happens if it’s five seconds old? Thirty seconds, five minutes, an hour, tomorrow morning? There are real real-time requirements, and plenty labeled real time because nobody asked the next question. ⟲
I teach three timings: ⟲
- Real time is synchronous: the caller waits for the answer. A user can’t take the next step until it comes back. It’s the hardest to build and has the most error handling. ⟲
- Near real time is anywhere from under a second to a minute, two, maybe five. There’s a big difference between sub-second and one to five minutes, and near real time is a lot cheaper and easier to maintain than real time. ⟲
- Batch is hourly, daily or weekly. Old school, and often exactly right. ⟲
Now put Steve Trucking’s arrows on that ladder. ⟲
| The arrow | How current it needs to be | Timing |
|---|---|---|
| Status out to Redrock, by webhook | As it happens: Redrock shows it to its own customers | Near real time, seconds |
| Latest truck position, FleetLink → Salesforce | A few minutes old is fine for “your truck is about 20 minutes away” | Near real time, minutes |
| Redrock’s manifest revisions | Before the truck leaves the dock | Near real time, minutes |
| Status events, Salesforce → Snowflake, through the integration layer | Today’s dashboards; nobody runs the company from the last second | Near real time or hourly batch |
| Status file to Keystone | Keystone asked for it each night | Batch, daily |
| Delivery counts to the finance ERP | Partners are invoiced monthly | Batch, daily is plenty |
Look at what’s missing: nothing on this landscape needs Salesforce to wait for another system’s answer. That’s not unusual. Real time costs more calls, more events, more processing, more contention and more operational complexity, so I want a reason for every one. If a nightly update meets the need, I’m not embarrassed to use one. Freshness is a requirement, not a default. ⟲
Salesforce’s Well-Architected framework makes the same point from the other side: the mechanism you pick sets how much you can lose and how stale a copy can get. Its Reliability (在新标签页中打开) guidance lists replication choices by that measure. Change Data Capture provides “near real-time replication with minimal development effort.” Platform events carry your own payloads, but need publish logic you build. A scheduled Bulk API 2.0 extraction is the simplest, “with an RPO equal to extraction frequency”: a nightly extract can be a day stale, by design. ⟲
Test knowledge. Match the timing to the mechanism. Waiting for an answer (request and reply) needs a synchronous call. Fire and forget from Salesforce: platform events (outbound messages are the older option). Keeping another system in step with Salesforce changes: Change Data Capture. Large scheduled loads: the Bulk API. Watch for scenarios that say “immediately” when the business only needs minutes. ⟲
Asking Every Minute
Section titled “Asking Every Minute”There’s a way to get near real time that looks simple: ask. A process outside Salesforce calls in on a schedule. “Has anything changed? Has anything changed? Has anything changed?” That’s polling. Once a minute doesn’t sound horrendous, until you do the math: 60 times 24 is 1,440 calls a day, for one question, from one system. Every call uses an API request from your allocation and puts its own load on Salesforce, whether or not anything changed. ⟲
Say the finance ERP wants Steve Trucking’s delivery counts, and someone builds a job that asks Salesforce every five minutes. That’s 288 calls a day and over 105,000 a year, for numbers the business invoices once a month. Almost every one of those calls comes back with nothing that matters. Well-Architected’s Resource and Cost Optimization (在新标签页中打开) pillar has a name for that: an integration that polls every five minutes and finds nothing “is pure waste.” A nightly batch serves finance better, at a fraction of the calls. ⟲
Now take Snowflake, which wants every status change, and soon. First question: who asks? Not Snowflake. A database stores; a process calls. Tables don’t start conversations. Something has to wake up, make the call, handle the error, retry and write the result. Salesforce can be that process for its own outbound calls, but Salesforce doesn’t poll itself on another system’s behalf. So when neither end runs the process you need, you add a third piece of software: middleware, the integration layer. ⟲
Look closely and even the “built-in” options are that third piece. Snowflake’s own Salesforce connector runs on Snowflake Openflow, which Snowflake describes as “an integration service” built on Apache NiFi; it polls Salesforce’s Bulk API 2.0 on a schedule, from every minute to once a day (Openflow (在新标签页中打开) and its Salesforce Bulk API connector (在新标签页中打开), checked 2026-10-27). Or you write a stored procedure that calls out through Snowflake’s external network access (在新标签页中打开) and schedule it as a task. Either way it’s a process, with its own credentials, schedule and failures, and someone has to own it. (When that connector’s page says it “supports Change Data Capture,” it means its own change detection by timestamp, not Salesforce’s change events.) Can it be done? Yes. Would I, and should I? That’s the architecture decision, not a feature of the database. ⟲
So the integration layer can poll: every minute, “anything changed?”, 1,440 calls a day, most finding nothing. Or Salesforce can tell it. I could build the telling myself: a record-triggered flow on the Work Order, query the fields, put them on a platform event, and the integration layer subscribes and writes them to Snowflake. It works. Then someone adds a field to the Work Order. Now I have to add it to the flow’s query, add it to the platform event, and change the subscriber and Snowflake’s table too. That’s code to maintain, forever, keeping up with the object’s definition. ⟲
Or I turn on Change Data Capture for the Work Order. No flow and no event to maintain: Salesforce publishes a change event for every create, update, delete and undelete, with the changed fields, and a new field is picked up automatically. Work Order and Service Appointment both support it, checked against the Object Reference (在新标签页中打开), Winter ‘27. ⟲
But count the zeros first. About 3,300 deliveries a day, with about 8 status changes each, is roughly 26,400 status changes a day, before any other field on the Work Order changes. CDC sends every change, not just status. And event delivery has a daily allocation: without an add-on, 50,000 delivered events in a rolling 24 hours for Performance and Unlimited Editions and 25,000 for Enterprise Edition, shared with high-volume platform events and counted per subscriber, so two subscribers use it twice (Change Data Capture Allocations (在新标签页中打开), checked 2026-10-27). When I first taught this, the warning was “you’re going to get a tsunami of data.” Today you can filter the stream (在新标签页中打开) in a custom channel, so the subscriber receives only the status changes it asked for. And the subscriber is middleware too: receiving change events means holding a subscription open to Salesforce’s Pub/Sub API, a job for an integration layer such as MuleSoft or a Kafka connector, not for the warehouse. Event-driven is better than polling for this arrow, but it still has a number of zeros. ⟲
The integration layer asks on a clock: 1,440 calls a day, most of them finding nothing. ⟲
The integration layer listens instead. Snowflake receives either way: a database stores; a process calls. ⟲
Salesforce’s own Best Practices for Deployments with Large Data Volumes (在新标签页中打开) gives an older form of the same advice for keeping another system in step with Salesforce. Use the SOAP API’s getUpdated() and getDeleted() calls “to sync an external system with Salesforce at intervals greater than 5 minutes,” and “use the outbound messaging feature for more frequent syncing” (Extracting Data from the API (在新标签页中打开), Winter ‘27, checked 2026-10-27). The idea still holds. On a schedule, ask only for what changed, and don’t forget what was deleted. When it has to be sooner than that, let Salesforce tell you. The mechanism has moved on: outbound messaging gets no further investment (module 3), so today the telling is usually Change Data Capture or platform events. ⟲
Test knowledge. Pulling changes out of Salesforce on a schedule:
getUpdated()andgetDeleted()return what changed and what was deleted in a time window, for intervals over 5 minutes. More often than that, let Salesforce send the change (Salesforce’s guide names outbound messaging; today, Change Data Capture or platform events). Expect a scenario where a full extract every few minutes is the wrong answer. ⟲
“零的个数”也适用于集成
Section titled ““零的个数”也适用于集成 ”Then: how much? Not “is it a lot?” Give me the zeros. And not just the daily number; tell me how it arrives. An integration team wants three numbers: transactions per second, bytes per second, and the activity window, the hours the traffic actually runs. You may have 24 hours in a day, but the data doesn’t arrive at 2 a.m. Steve Trucking’s crews work about twelve hours, so that’s the window. ⟲
| Steve Trucking’s traffic | A day | Per second, in a 12-hour window | Bytes |
|---|---|---|---|
| Truck positions from FleetLink | about 200,000 readings | about 4.6 | tiny: a position and a time |
| Delivery status changes | about 26,400 | about 0.6 | small |
| Delivery photos | about 13,200 photos | about 0.3 | heavy: at about 4 MB each, 53 GB a day, 1.2 MB every second |
Look at the photos: under one transaction every three seconds, and still the heaviest arrow on the landscape. Positions are the opposite: the most transactions, almost no bytes. A lot of data with low transactions per second, or high transactions per second with little data: they have completely different behavioral profiles. Count both. And plan for the busiest season, not the average day. ⟲
I also think of integration traffic in three shapes: ⟲
- Singles. One record at a time: a status change, an order. Exactly right for transactional activity. But send 100,000 records one at a time as fast as you can, and a reasonable pattern becomes a machine gun: every call has overhead, may run automation and competes for resources. ⟲
- Sets. Bundle them, tens or hundreds per call, and let the receiver process sensible groups. Redrock’s evening manifest is a set. For many integrations, the middle ground is the best fit. ⟲
- Bulk. Hundreds of thousands or millions of records, like a historical load. Don’t pretend two million records are two million little real-time transactions. Salesforce has the Bulk API for bulk work: in class I call it the 18-wheeler next to the bank teller. ⟲
It’s a teaching model, not a limits table, but it makes you respect the zeros. ⟲
Salesforce’s guide does draw one line in numbers: “Any data operation that includes more than 2,000 records is a good candidate for Bulk API 2.0”; fewer than that should be “bulkified” synchronous calls, in REST (Composite, for example) or SOAP. And when you update, “send only fields that have changed” (Loading Data from the API (在新标签页中打开), checked 2026-10-27). Sending every field every time is the integration version of the machine gun. Chapter 10 has the rest of that guide’s loading advice. ⟲
Singles, sets and bulk. A teaching model, not platform limits. ⟲
Test knowledge. For hundreds of thousands or millions of records, the answer is the Bulk API, not many single REST calls. Salesforce’s line: more than 2,000 records is a good candidate for Bulk API 2.0; fewer, bulkified synchronous calls. When API limits bite on a set of related records of different objects, look at the composite resources, which carry several operations in one call. When updating, send only the fields that changed. ⟲
集成的数据量会变成数据的数据量
Section titled “集成的数据量会变成数据的数据量 ”假设一个外部系统每分钟创建 500 条记录。那就是每小时 30,000 条,如果持续运行,每天 720,000 条:一年几亿次操作。也许它不是一直在运行;也许大部分是更新。好,这正是我要数字的原因。因为接下来数据问题就开始了。它们落在哪个对象上?所有权如何分布?它们共用父记录吗?会触发什么自动化,重新计算什么共享,会不会创建历史记录,有没有汇总,保留期是多久?我们会不会制造出一个热点?这些记录我们真的每一条都需要放在 Salesforce 里吗?
An integration can create a large-data-volume problem on its own. “Every time FleetLink sends a GPS position, we’ll create a Salesforce record.” That’s 200,000 a day: 73 million records a year. Before I care whether that’s REST, events or middleware, I ask: why would we put 73 million GPS readings a year into the transactional data model? At Checkpoint 1 we decided not to; only the latest position matters to the org. The integration mechanism doesn’t answer that question. It’s a data architecture decision. Sometimes understanding the integration redesigns the model; sometimes it redesigns the integration; sometimes it decides not to move the data at all. ⟲
数据流动不是免费的
Section titled “数据流动不是免费的 ”每一份副本都有后果:存储、新鲜度、同步、安全、隐私、主数据管理、删除、对账。把客户数据从 ERP 复制到 Salesforce,你就多了一种需要治理的表示。谁拥有它?它能过时到什么程度?如果有人在 Salesforce 里改了它,或者五分钟后 ERP 又发来一个不同的值,或者客户要求被遗忘,或者一个智能体更新了它,会怎样?箭头承载的不只是字节。它还在创造另一个必须治理企业数据的地方。
Two of the seven questions get the next module. What’s the key? If Redrock resends delivery 8472914, does Salesforce create, update, reject or link? Without a stable key, retries become duplicates and reconciliation becomes guesswork; that’s why Checkpoint 1 gave every Work Order a key that matches the partner’s order. Who may write? If the finance ERP owns billing terms and Salesforce owns the appointment and the crew, an integration doesn’t mean “the ERP may update the record.” It means “the ERP may update these fields.” That’s chapter 6’s authority map made executable. A system-of-record diagram that doesn’t change write behavior is decoration. ⟲
当它失败时
Section titled “当它失败时 ”It will. Here’s our landscape again, the same places, with the arrow we zoomed in on. Tonight’s Redrock manifest, 370 deliveries, reaches the integration layer, and the call into Salesforce times out. ⟲
The arrow fails, on the whole landscape. ⟲
Now zoom in on that one arrow. Leave everything else behind: Salesforce on the left, the integration layer on the right, and the call between them. ⟲
One arrow, one timeout. ⟲
Before you read on, stop and answer it. Did the manifest save? There are three honest answers. All of it: Salesforce saved all 370 Work Orders, and only the reply was lost on the way back. None of it: the call never finished. Some of it: 367 saved and 3 were rejected by a validation rule, and nobody has read the errors yet. Salesforce knows which one happened. The integration layer, the client, only knows it didn’t get an answer. ⟲
Salesforce knows what it saved. The integration layer only knows it heard nothing back. ⟲
Now the integration layer does what clients do: it sends the manifest again. If every Work Order is matched by Redrock’s order and delivery reference, the resend updates what’s there and creates only what’s missing. If it isn’t, and the first call had saved, Steve Trucking now has 740 Work Orders for 370 deliveries, and two crews may be sent to the same door. Same timeout, very different data. That’s why the key comes before the mechanism (module 2), and why somebody has to own knowing whether it all arrived (module 3). ⟲
The resend. Safe with a key; duplicates without one. ⟲
A timeout is only one of the common failures. A malformed payload, an expired token, a validation rule rejecting a record, a server down, record 7,428 of 20,000 failing, an event delivered twice. Here integration and data architecture become inseparable. The integration architect thinks about retries, queues, replay, error handling and monitoring. The data architect thinks about duplicates, missing records, partial state, stale values, broken relationships and the wrong system writing. Two views of the same failure. ⟲
So for every arrow I ask the same things. On every outbound arrow: where do I log, what do I tell the user, and how do I retry? On every inbound arrow: how do they recover? Errors will happen. ⟲
而且“API 返回了 200”不等于数据质量。接口是工作了。预期的 10,000 条记录都到了吗,还是只到了 9,997 条?有三条被拒绝了吗?重试有没有造成重复?改变的是不是正确的记录?转换有没有损坏某个值?我们有没有覆盖了不属于我们的字段?这就是为什么我那条反复出现的规则在这里如此贴切:**信任,但要验证。**模块 3 会把它讲具体。
Beyond the exam: what AI changes. An agent looking up a delivery in another system is an integration. An agent updating Salesforce through an API, or calling Salesforce’s hosted MCP servers, is an integration; an agent retrying after a failure is an integration retry. The caller is new; the questions aren’t. Who starts it? The agent, on behalf of a user, with that user’s permissions. How much? An agent can ask the same question many times a day, so the number of zeros grows with every conversation (chapter 16’s tireless assistant (coming soon)). Treat every agent read and write path as an arrow, with identity, authority, volume, failure handling and observability. ⟲
架构师在这里决定什么
Section titled “架构师在这里决定什么 ”- What every important arrow means: who starts it, which way the data moves, how current it must be, and its volume and shape. ⟲
- Whether “real time” is a requirement or a habit, and which timing each arrow really needs. ⟲
- Which process runs each arrow (Salesforce, the other system, or middleware), whether it polls or listens for change, and what its events cost in allocations. ⟲
- 集成是否通过自动化、锁定、共享、存储或数据量增长给数据模型带来压力。
- 数据到底该不该流入 Salesforce。
- 在选择机制之前,集成需要什么样的稳定键和写入权限。
- 谁能看到足够多的交互来验证成功并负责恢复。
Diagrams make systems look clean. Real integrations are conversations between systems that move data under rules and fail in specific ways. You don’t have to build each one, but once the arrow starts moving data, the integration design becomes part of your data architecture. So before REST, Bulk API, events or middleware, zoom in on the arrow and know what it means. Then design it. ⟲
- On this site: Steve’s Number of Zeros for Integrations, the method from this module with four worked examples and a calculator to use with the business in the room. ⟲
- Salesforce, Best Practices for Deployments with Large Data Volumes (在新标签页中打开), Winter ‘27 (last updated September 18, 2026): Loading Data from the API (在新标签页中打开) and Extracting Data from the API (在新标签页中打开), checked 2026-11-01. ⟲
- Salesforce Architects, Data Integration with Salesforce (在新标签页中打开) (decision guide), checked 2026-11-01. ⟲
- Salesforce Architects, Well-Architected, Reliability (在新标签页中打开) and Resource and Cost Optimization (在新标签页中打开), checked 2026-11-01. ⟲
- Snowflake, Openflow (在新标签页中打开), checked 2026-11-01. ⟲
- Salesforce Developers, Change Data Capture Allocations (在新标签页中打开) (Change Data Capture Developer Guide), checked 2026-11-01. ⟲
- Integration Architect 课程:一次调用如何运作和时序与数据量 (coming soon)。
- Snowflake, About the Openflow Connector for Salesforce Bulk API (在新标签页中打开), checked 2026-11-01. ⟲
- Snowflake, External network access overview (在新标签页中打开), checked 2026-11-01. ⟲
- Salesforce Developers, Object Reference: StandardObjectNameChangeEvent (在新标签页中打开), Winter ‘27, checked 2026-11-01. ⟲
- Salesforce Developers, Change Data Capture Developer Guide: Add a Filter with Tooling API (在新标签页中打开), checked 2026-11-01. ⟲
