ข้ามไปยังเนื้อหา

ระบบอัตโนมัติระหว่างการโหลด

มีให้อ่านอีก 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)

In a plant room, the valves beside a pump stand closed and its cover is off, while a bypass pipe with an open valve carries the flow around it.
ภาพสร้างด้วย AI

โมดูลที่ 3 จาก 5 ในบท การย้ายข้อมูลและการซิงก์ บทที่ 10 ของหลักสูตร Data Architect แต่ละโมดูลอ่านแยกกันได้ ก่อนหน้า: การโหลดในปริมาณมาก · ถัดไป: สุดสัปดาห์สลับระบบ

คำถามที่โมดูลนี้ตอบ: อะไรควรเกิดขึ้นกับระบบอัตโนมัติของ Salesforce ขณะที่ข้อมูลการย้ายกำลังถูกโหลด?

RouteDesk’s records are ready: about 707,000 of them, prepared, sorted by parent, rehearsed. You start the load, and Salesforce starts doing exactly what you configured it to do. Flows fire, triggers run, validation rules evaluate, emails send, tasks get created, rollups calculate, integrations launch, events publish. Your 707,000-record migration isn’t performing 707,000 operations anymore. It’s performing 707,000 records multiplied by everything each record causes. That’s a different migration. ⟲

Here’s the landscape again, the weekend RouteDesk retires. The migration arrow is amber. Now look at what else leaves Salesforce when a Work Order is created or changes status. ⟲

The arrows a load sets off Steve Trucking's landscape from Checkpoint 1, in the same places, the weekend RouteDesk retires. The migration arrow from RouteDesk into Salesforce is in amber. Three arrows leaving Salesforce are red with an X, because normal automation would fire them for every migrated Work Order: status events to the integration layer, delivery counts to the integration layer, and the day-before texts to the SMS and email provider. Underneath: load 196,400 Work Orders with the automation on, and three more arrows fire for every one of them: status events, delivery counts and day-before texts. {"author": "Steve Simpson", "blueprint": "1.0.1", "builder": "standard 1.54.0", "built": "2026-10-30", "id": "DGM-DA-MG-30", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "system-landscape 0.13.0", "theme": "stevetecharc 1.4.0"} ABOVE: IDENTITY, APPEXCHANGE, WEB PEOPLE RIGHT: INTERNAL SYSTEMS BELOW: CUSTOMER CHANNELS BOTTOM RIGHT: PARTNERS AND PROVIDERS Dispatch coordinators 45, inside 9 partner DCs Delivery crews ~700 on 330 trucks Care and office staff 100: service, ops, finance Retail Partner users ~300 at 3 partners Recipients ~1 million a year Corporate IdP SSO for office staff only Retail Partner portal Tracking page INTEGRATION Snowflake status history, analytics FleetLink raw GPS stays here Finance ERP invoices partners, pays crews Photo storage 4–5 million a year, off core RouteDesk retiring: 8 years, ~5 million deliveries Phone care agents Email email-to-case SMS and email provider day-before message, with a link Redrock REST API, webhooks Keystone CSV over SFTP Brightwave EDI through a third-party network Salesforce Field Service, one US org a link, no login office staff only calls cases in manifests in status out manifests in status out manifests in status out upserts, partner key status events status events latest position only delivery counts delivery counts photos, from the crews' app day-before, with a link what's still open: migrated once Salesforce a community people identity, apps, web an internal system a customer channel the integration layer starts at the system that opens the connection; the label says what moves red with an X: fires for every migrated record unless you decide otherwise a shared certificate: trust, no direct call the migration Load 196,400 Work Orders with the automation on, and three more arrows fire for every one of them: status events, delivery counts and day-before texts. © 2026 Twinshark LLC · stevetecharc.com
คลิกเพื่อขยาย

One arrow in. Three more arrows out, for every record, unless we decide otherwise. ⟲

Every one of those arrows was designed in chapter 9 for a delivery that just happened: a status changed, so tell the partner and Snowflake; a delivery finished, so count it for invoicing; a delivery is tomorrow, so text the Recipient. The load creates 196,400 Work Orders in one weekend, and about 190,000 of them arrive already completed. To the automation, each one looks like a delivery that just happened. ⟲

ระบบอัตโนมัติไม่รู้ว่านี่คือการย้ายข้อมูล

หัวข้อที่มีชื่อว่า “ระบบอัตโนมัติไม่รู้ว่านี่คือการย้ายข้อมูล ”

Salesforce sees a record transaction. It doesn’t know “this is historical data loaded during a controlled cutover.” A flow sees a new Account and does what it was built to do: creates an onboarding task, sends a welcome email, publishes an event, updates a related record, calls another system. Correct when a sales rep creates one account on Tuesday afternoon. Completely wrong when a migration creates 800,000 historical accounts on Saturday night. Same operation, different business context. At Steve Trucking, a Work Order arriving with a status of Completed looks exactly like a crew finishing a delivery five minutes ago. ⟲

ดังนั้นสำหรับการย้ายข้อมูลครั้งใหญ่ ผมเริ่มจากหลักนี้: ระบบอัตโนมัติทางธุรกิจตามปกติไม่ควรทำงานกับการโหลดแบบไม่ลืมหูลืมตา นั่นไม่ได้แปลว่า “ปิดทุกอย่าง” แต่หมายถึงระบบอัตโนมัติที่สำคัญทุกตัวได้รับการตัดสินใจอย่างตั้งใจ และผมไม่อยากให้คำตอบถูกค้นพบเพราะ production ส่งอีเมลไป 400,000 ฉบับ

For each automation, I ask what it does and what happens if it doesn’t run, and then I put it in one of three categories. ⟲

ไม่ต้องใช้ (กำจัดทิ้ง) พฤติกรรมนั้นไม่ควรเกิดกับเรกคอร์ดที่ย้ายมา ลูกค้าที่อยู่กับเรามาแปดปีไม่ต้องการ “ยินดีต้อนรับสู่บริษัทของเรา!” insert บัญชีหนึ่งบัญชี มันส่งอีเมลหนึ่งฉบับ โหลดหนึ่งล้านบัญชี และผมไม่ต้องการอีเมลหนึ่งล้านฉบับ

จำลองมัน ระบบอัตโนมัติไม่ควรทำงาน แต่ผลลัพธ์ที่มันสร้างยังจำเป็นอยู่ Flow หนึ่งที่ทำงานตอนสร้างบัญชีคำนวณ Customer Segment บัญชีที่ย้ายมาต้องมี segment ที่ถูกต้อง แต่การรัน flow ทั้งตัวห้าล้านครั้งแพงหรือมีผลข้างเคียง เราจึงคำนวณ segment ในการแปลงแล้วโหลดผลลัพธ์ เราไม่ได้เพิกเฉยต่อกฎทางธุรกิจ เราทำงานของระบบอัตโนมัติไว้ในการโหลด

เลื่อนมัน ผลลัพธ์จำเป็น แต่ไม่ใช่ภายในธุรกรรมการโหลด โหลดโดยปิดระบบอัตโนมัติและตั้งธงไว้ แล้วกระตุ้นกระบวนการแบบ batch ให้ตามเก็บ: คำนวณใหม่ สร้างเรกคอร์ดที่ขึ้นต่อกัน เผยแพร่สิ่งที่ระบบปลายทางต้องการ การเลื่อนทำให้การโหลดเร็วขึ้นและควบคุมได้มากขึ้น โดยไม่ต้องสละผลลัพธ์

และบางครั้งคุณก็เปิดมันไว้ สำหรับการโหลดขนาดเล็กที่ธุรกิจต้องการให้กระบวนการปกติทำงาน ก็ปล่อยให้ระบบทำสิ่งที่มันทำ นั่นก็เป็นการเลือกเช่นกัน ตราบใดที่มันเป็นการเลือก

ไม่ว่าคุณจะเลือกอะไร นี่คือกฎที่ผมสอน: ทุกครั้งที่คุณปิดระบบอัตโนมัติ คุณรับผิดชอบเต็มที่ต่อการที่ตรรกะทางธุรกิจนั้นไม่ได้เกิดขึ้น คุณต้องเข้าใจระบบอัตโนมัติทุกตัวก่อนตัดสินใจ

Don't need it, simulate it, defer it A decision tree, read left to right, with three questions and four answers. First question: should it happen for migrated data? If no: don't need it, for example status messages to partners for deliveries they closed weeks ago. If yes, the second question: must it happen inside the load? If yes: let it run, deliberately, for example the rule that every Work Order has a partner. If no, the third question: can the preparation set the result, a value rather than a side effect? If yes: simulate it, for example the Work Order's status, mapped in the preparation data store. If no: defer it, for example status history to Snowflake, as one backfill after the load. Underneath, Steve's rule: any time you turn an automation off, you're taking full responsibility for that business logic not happening. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.48.0", "built": "2026-10-27", "id": "DGM-DA-MG-31", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.4.0", "theme": "stevetecharc 1.4.0"} THE QUESTIONS THE ANSWERS Should it happen for migrated data? ask it of every automation Must it happen inside the load? or can it come later Can the preparation set the result? a value, not a side effect Don't need it status messages to partners for deliveries closed weeks ago Let it run, deliberately the rule that every Work Order has a partner Simulate it the Work Order's status, mapped in the preparation data store Defer it status history to Snowflake: one backfill after the load no yes yes no yes no Any time you turn an automation off, you're taking full responsibility for that business logic not happening. © 2026 Twinshark LLC · stevetecharc.com
คลิกเพื่อขยาย

Three questions, four answers, one decision per automation. ⟲

Test knowledge. For each automation on a large load, decide: not needed for migrated data (bypass it), needed but its result can be set in the data (simulate it in the transformation), needed but not inside the load (defer it to a batch afterward), or needed inside the load (let it run). Expect a scenario where blindly running automation creates unwanted emails, tasks or integration calls, and one where turning it off silently loses a required result. ⟲

แผนบอกว่า “ปิดระบบอัตโนมัติ” ระบบอัตโนมัติตัวไหน? อย่างไร ใคร เมื่อไหร่? เรารู้ได้อย่างไรว่ามันปิดแล้ว และรู้ได้อย่างไรว่ามันเปิดกลับแล้ว? ผลลัพธ์ไหนที่มันสร้างตามปกติยังต้องมีอยู่หลังจากนั้น? เกิดอะไรขึ้นถ้าผู้ใช้อยู่ในระบบขณะที่มันปิด หรือการย้ายข้อมูลล้มเหลวกลางทาง? การปิดบางอย่างคือการกระทำด้านปฏิบัติการ สถาปัตยกรรมต้องการวงจรชีวิตทั้งหมด: สถานะปกติ สถานะการย้ายข้อมูล การกลับสู่ปกติ และหลักฐานว่าเรากลับมาแล้ว

And before you decide what to switch off, find out what’s still switched on. Old automation runs on migrated records too. Salesforce ended support for Workflow Rules and Process Builder on December 31, 2025, but “your active Workflow Rules and Process Builder processes continue to run as they did before” (Workflow Rules & Process Builder End of Support (เปิดในแท็บใหม่), Salesforce Help, checked 2026-10-27). Well-Architected points out the cost: an org “carrying dozens of Process Builders left over from prior implementations … pays to evaluate every one of them on every relevant record save,” and its advice is to “migrate remaining Process Builders to Flow; don’t just deactivate them” (Resource and Cost Optimization (เปิดในแท็บใหม่), checked 2026-10-27). A migration is a good reason to clear them out first, so 707,000 records aren’t run through automation nobody remembers. ⟲

จุดยืนที่หนักแน่นกว่าของผม: ระบบอัตโนมัติที่สำคัญควรมีทางเลี่ยงที่ควบคุมได้ แม้ไม่มีการย้ายข้อมูลอยู่ในแผน การย้ายข้อมูลไม่ใช่เหตุผลเดียวที่คุณจะต้องการมัน การแก้ไขขนาดใหญ่ การแก้ข้อมูล การเติมข้อมูลย้อนหลัง การซ่อมการผสานรวม การกู้คืนฉุกเฉิน: บางครั้งคุณต้องรันการดำเนินการที่ควบคุมได้โดยไม่มีระบบอัตโนมัติปกติทุกชิ้น ถ้าวิธีเดียวคือแก้ flow ใน production ปิด trigger หรือลบกฎการตรวจสอบความถูกต้อง เราก็ทำให้งานปฏิบัติการอันตรายโดยไม่จำเป็น และคุณปิด trigger ใน production เฉยๆ ไม่ได้: นั่นคือการ deploy พร้อมการทดสอบของมัน

The standard answer is a bypass (some teams call it a kill switch): the first thing the trigger or flow does is check a switch, and skip itself if the switch is on. Decide the scope: a global switch for the whole org, one per object, one per automation, or one for particular users, such as the data load user or anyone holding a permission. Put it in your flows as well as your triggers. Flows are easy to deactivate, but a user-specific switch lets everyone else keep working. I consider flows visual programming: whether you’re writing code or programming visually, you’re still programming, and programs need this. ⟲

And here’s the part teams miss: the bypass is part of the original design. It isn’t something you build the week you need it. Every trigger and flow gets its bypass when it’s first built. It’s tested both ways, switched on and switched off, like any other behavior. And it goes to production with the automation, long before any migration, so on cutover weekend it’s already there, already tested, and ready to switch on. A bypass written in a hurry for the load is new, untested code going into production on the riskiest weekend of the project. Salesforce’s Record-Triggered Automation decision guide is just as firm: “A well-architected Salesforce organization requires a consistent and reliable mechanism to bypass automation. This is not an optional feature, but a core operational requirement” (Record-Triggered Automation (เปิดในแท็บใหม่), Salesforce Architects decision guide, checked 2026-10-27). ⟲

Salesforce says the same thing in its own words. Its Well-Architected list of automation anti-patterns includes “Flows must be manually deactivated prior to bulk data loads” (Automation Patterns (เปิดในแท็บใหม่), Operational Excellence, checked 2026-10-27). If your load plan says “deactivate these twelve flows on Friday night,” that’s the anti-pattern. ⟲

Test knowledge. Build a bypass into triggers and flows when they’re first built (a check of a custom permission, a custom setting or custom metadata at the start), test it on and off, and deploy it ahead of time, so large loads can skip them without editing or deactivating anything in production. Scope it: by object, by automation, or by user, such as the migration user. Deactivating flows by hand before a bulk load is an anti-pattern in Salesforce’s own Well-Architected guidance. ⟲

So what does a bypass actually look like? Three parts: a place to keep the switch, a check at the top of every trigger and flow, and the same check in the validation rules you decide to relax. Salesforce gives you three places to keep it, and each one decides who the switch applies to. ⟲

Where the switch livesWho it applies toGood for
A custom permission, granted by a permission setOnly the users who hold itThe usual migration bypass: give it to the migration user for the load, take it away after
A hierarchy custom settingThe whole org, one profile, or one userA global “automation off” for everyone, or a switch for one profile or one user
A custom metadata record per automationEveryone, for that one automationSwitching off one specific automation, deployed and versioned like code

The hierarchy custom setting is the one that does global, profile and user in one place. Salesforce’s description: it “checks the organization, profile, and user settings for the current user and returns the most specific, or lowest, value” (Define Custom Settings (เปิดในแท็บใหม่), Salesforce Help, checked 2026-10-27). Set it off for the org, on for the migration user, and the migration user gets the bypass while everyone else gets normal automation. For most other configuration Salesforce now steers you to custom metadata instead, which deploys with your code; I’d use that for the per-automation switches. ⟲

In Apex, the check is the first thing the trigger does. Here’s what it could look like on the Work Order, with a hierarchy custom setting called Automation_Bypass__c and a custom permission called Bypass_Automation: ⟲

trigger WorkOrderTrigger on WorkOrder (after insert, after update) {
// The hierarchy custom setting: the user's value, else the profile's, else the org's
Automation_Bypass__c settings = Automation_Bypass__c.getInstance();
// Bypass if the setting says so, or if this user holds the custom permission
Boolean bypass = settings.Disable_Triggers__c == true
|| FeatureManagement.checkPermission('Bypass_Automation');
if (bypass) {
return; // no side effects; the record still saves
}
WorkOrderStatusOut.publish(Trigger.new, Trigger.oldMap);
}

getInstance() returns the setting “for the current user,” merged from the lowest level that’s defined (Custom Settings Methods (เปิดในแท็บใหม่)), and FeatureManagement.checkPermission “checks whether a custom permission is enabled” (FeatureManagement Class (เปิดในแท็บใหม่); both Apex Reference Guide, Winter ‘27, checked 2026-10-27). ⟲

And one switch per automation, so the bypass is scoped instead of “skip everything.” A custom metadata type, Automation_Switch__mdt, with one record per automation: ⟲

public with sharing class WorkOrderStatusOut {
public static void publish(List<WorkOrder> orders, Map<Id, WorkOrder> oldOrders) {
// One record per automation; switched off here, it's off everywhere it's deployed
Automation_Switch__mdt sw = Automation_Switch__mdt.getInstance('WorkOrder_Status_Out');
if (sw != null && sw.Is_Off__c) {
return;
}
// ... publish the status change for the partners
}
}

getInstance(developerName) reads one custom metadata record by its name (Custom Metadata Type Methods (เปิดในแท็บใหม่), Apex Reference Guide, checked 2026-10-27). ⟲

In a flow, it’s the same idea: the first element is a decision. ⟲

A bypass at the top of a flow A record-triggered flow, top to bottom. It starts when a Work Order is created or changes. The first element is a question: is the bypass on for this user, through a custom permission or a setting for the org, a profile or one user? If yes, the flow ends and does nothing; the record still saves, with no side effects. If no, the flow carries on to its normal work, highlighted: publish the status to the partners, for everyone else. Underneath: the check comes first; switch it on for the migration user, and the flow steps aside while the record saves. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.48.0", "built": "2026-10-27", "id": "DGM-DA-MG-33", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "flow/decision 0.1.0", "theme": "stevetecharc 1.4.0"} A Work Order is created or changes the record-triggered flow starts Is the bypass on for this user? a custom permission, or a setting for the org, a profile or one user End: do nothing the record still saves; no side effects Publish the status to the partners the normal work, for everyone else yes no The check comes first. Switch it on for the migration user, and the flow steps aside while the record saves. HOW TO READ IT a step the step that matters most a question an answer yes goes right to an answer; no goes down to the next question © 2026 Twinshark LLC · stevetecharc.com
คลิกเพื่อขยาย

The check comes first. Switched on, the flow steps aside. ⟲

The decision’s condition reads the same two switches, through flow’s global variables: $Permission is “the custom permission access of the user running the flow,” and $Setup reads hierarchy custom settings (Global Variables Resource (เปิดในแท็บใหม่), Salesforce Help, checked 2026-10-27). As a formula resource: ⟲

{!$Permission.Bypass_Automation} || {!$Setup.Automation_Bypass__c.Disable_Flows__c}

In a validation rule, the bypass is one more condition. Here’s R12’s install rule, with the migration user allowed through (the field names are examples): ⟲

AND(
NOT($Permission.Bypass_Automation),
ISPICKVAL(Status, "Completed"),
Install_Required__c,
NOT(Install_Checklist_Complete__c)
)

Validation rules reference a custom permission as $Permission.Custom_Permission_Name (How to Reference a Custom Permission in a Formula, Workflow Rule, or Validation Rule (เปิดในแท็บใหม่), Salesforce Help, checked 2026-10-27). ⟲

Salesforce’s decision guide calls custom permissions “the modern, scalable standard for implementing bypass logic,” and notes a bypass can be granted to one user, “or even temporarily with a specific expiration date/time” (Record-Triggered Automation (เปิดในแท็บใหม่), checked 2026-10-27). That’s the migration window, built into the grant. ⟲

These are examples to adapt, not a framework to paste in: build yours, test it in a sandbox, and test that the switch turns back off. And remember what you’ve built. A bypass is a permission to skip business rules. Grant it to the migration user for the migration window, record who has it, and take it away when the load is done (module 4 puts that in the runbook). ⟲

Test knowledge. Know the three places to keep a bypass and who each applies to: a custom permission (only the users whose permission sets grant it; checked with $Permission in flows and validation rules, FeatureManagement.checkPermission in Apex), a hierarchy custom setting (the org, a profile or a user, the most specific value winning; $Setup in flows and formulas, getInstance() in Apex), and custom metadata (one switch per automation, deployable). ⟲

ทางเลี่ยงไม่ได้หมายความว่าผู้ใช้สำหรับการย้ายข้อมูลเพิกเฉยต่อกฎทุกข้อใน Salesforce ระบบอัตโนมัติตัวหนึ่งควรถูกเลี่ยง อีกตัวต้องยังทำงาน กฎการตรวจสอบความถูกต้องที่ปกป้องข้อเท็จจริงพื้นฐานยังสำคัญ การแจ้งเตือนไม่สำคัญ การผสานรวมปลายทางต้องถูกระงับ ความสัมพันธ์ที่จำเป็นยังต้องถูกตรวจ ผมจึงต้องการทางเลี่ยงที่ตั้งใจและมีขอบเขต ไม่ใช่ Migration_Mode__c = true แล้วก็ไม่มีอะไรสำคัญอีกต่อไป เส้นทางการย้ายข้อมูลยังมีกฎ เพียงแต่เป็นกฎที่เหมาะกับการย้ายข้อมูล

และทางเลี่ยงควรแทนบริบทด้านปฏิบัติการ ไม่ใช่อุบัติเหตุ ตัวตนเฉพาะสำหรับการย้ายข้อมูล (โมดูลที่ 2) custom permission เมตาดาต้าการตั้งค่า feature flag หรือหลายอย่างรวมกัน จดจำงานย้ายข้อมูลที่ได้รับอนุมัติได้ ตัวตนเป็นส่วนหนึ่งของการควบคุมได้ แต่ผมไม่ต้องการให้ระบบอัตโนมัติทุกตัวเขียนตายตัวว่า User.Name = 'Migration User' นั่นเปราะบาง จงแสดงเจตนา: ถ้านี่คือการดำเนินการย้ายข้อมูลที่ได้รับอนุมัติ ให้ข้ามผลข้างเคียงนี้

“Close Date ต้องมีเมื่อ Opportunity เป็น Closed Won” คือข้อเท็จจริงของข้อมูลจริงๆ เก็บมันไว้สำหรับโอกาสทางการขายในอดีต กฎที่บังคับฟิลด์ของกระบวนการปัจจุบันซึ่งเพิ่มมาเมื่อสามปีก่อนนั้นต่างกัน: เรกคอร์ดจากสิบปีก่อนไม่เคยมีมัน และการแต่งค่าขึ้นมาทำให้ข้อมูลแย่ลง คำถามไม่ใช่ “เราปิดกฎการตรวจสอบความถูกต้องไหม?” แต่คือ กฎไหนแทนความจริงของข้อมูลที่ยั่งยืน และกฎไหนแทนกระบวนการโต้ตอบของวันนี้? นั่นคือคำถามของสถาปนิกข้อมูล

Steve Trucking has one of each. Every Work Order must have a Retail Partner: that’s enduring truth, and it stays on for the load; a RouteDesk delivery without one goes to quarantine (module 1). But requirement R12 says an install can’t be closed without a completed checklist and specific photos, the water line, the drain line, the level. That’s today’s process, built for crews with the new mobile app. RouteDesk’s completed installs never had those photos. Bypass that rule for the migration identity, and load them as completed. Don’t invent photos. ⟲

กลิ่นที่ต้องระวัง: ปลายทางต้องการค่า ต้นทางไม่มี เลย “ใส่ ‘Unknown’ ให้หมดเลย” ถ้า Unknown เป็นค่าที่อนุมัติแล้วซึ่งอธิบายสถานะได้จริง ก็ได้ ถ้าเรากำลังใส่ค่าปลอมเพื่อผ่านการตรวจสอบ เรากำลังทำลายข้อมูลเพื่อเอาใจแอปพลิเคชัน ผมยอมออกแบบข้อยกเว้นสำหรับการย้ายข้อมูล ฟิลด์ประวัติที่เป็น null ได้ กฎการแปลง หรือค่าสถานะแบบเดิม ดีกว่าแสร้งว่าเรารู้สิ่งที่เราไม่รู้

โหลด 2 ล้านบัญชี ระบบอัตโนมัติสร้างงาน 2 งานต่อบัญชี: 4 ล้านงาน ตั้งใจ หรืออุบัติเหตุ? แล้วแต่ละงานก็กระตุ้น flow อีกตัว ระบบอัตโนมัติของบัญชีอัปเดตเรกคอร์ดแม่ เผยแพร่ event คำนวณอย่างอื่นใหม่ ประสิทธิภาพของการย้ายข้อมูลไม่ใช่ว่า Bulk API แทรกบัญชีได้เร็วแค่ไหน ภาระงานจริงคือกราฟธุรกรรมที่การแทรกเหล่านั้นสร้างขึ้น จำนวนเลขศูนย์ถูกคูณผ่านระบบอัตโนมัติ

Now zoom in on RouteDesk’s three red arrows and count. ⟲

Automation multiplies the Number of Zeros On the left, highlighted, the load: 196,400 Work Orders, about 190,000 of them already delivered. On the right, what normal automation would reach: Snowflake, for status history; the partners, Redrock, Keystone and Brightwave; the finance ERP, which invoices the partners; and the Recipients, who get day-before texts. First, every arrow is red with an X: 196,400 change events to Snowflake, 190,000 old statuses to the partners, delivery counts already invoiced to the finance ERP, and texts for old deliveries to the Recipients. Then the controlled path: the red arrows are gone; Snowflake gets one backfill after the load, the Recipients get texts only for the open deliveries, as normal, and nothing goes to the partners or the finance ERP. Underneath: the load's real size is every record times everything each record sets off; keep only the outcomes you need. THE LOAD WHAT NORMAL AUTOMATION WOULD DO 196,400 Work Orders about 190,000 already delivered Snowflake status history The partners Redrock, Keystone, Brightwave Finance ERP invoices the partners Recipients day-before texts 196,400 change events 190,000 old statuses counts already invoiced texts for old deliveries The load's real size is every record times everything each record sets off. Keep only the outcomes you need. HOW TO READ IT the load © 2026 Twinshark LLC · stevetecharc.com
คลิกเพื่อขยาย

Every record, times everything it sets off. ⟲

Chapter 9 turned on Change Data Capture for Work Orders, so Snowflake’s subscriber receives a change event for every create. That’s about 196,400 events in one weekend, and without an add-on the daily allocation for delivered events is 50,000 in Performance and Unlimited Editions, counted per subscriber (Change Data Capture Allocations (เปิดในแท็บใหม่), checked 2026-10-27). The partners would get status messages for about 190,000 deliveries they closed weeks ago. The finance ERP would count deliveries it has already invoiced, and the partners would be billed twice. And Recipients would get texts about deliveries that already happened. ⟲

Automation multiplies the Number of Zeros On the left, highlighted, the load: 196,400 Work Orders, about 190,000 of them already delivered. On the right, what normal automation would reach: Snowflake, for status history; the partners, Redrock, Keystone and Brightwave; the finance ERP, which invoices the partners; and the Recipients, who get day-before texts. First, every arrow is red with an X: 196,400 change events to Snowflake, 190,000 old statuses to the partners, delivery counts already invoiced to the finance ERP, and texts for old deliveries to the Recipients. Then the controlled path: the red arrows are gone; Snowflake gets one backfill after the load, the Recipients get texts only for the open deliveries, as normal, and nothing goes to the partners or the finance ERP. Underneath: the load's real size is every record times everything each record sets off; keep only the outcomes you need. {"author": "Steve Simpson", "blueprint": "1.0.0", "builder": "standard 1.48.0", "built": "2026-10-27", "id": "DGM-DA-MG-32", "rights": "\u00a9 2026 Twinshark LLC. All rights reserved.", "template": "cells 0.4.0", "theme": "stevetecharc 1.4.0"} THE LOAD WHAT NORMAL AUTOMATION WOULD DO 196,400 Work Orders about 190,000 already delivered Snowflake status history The partners Redrock, Keystone, Brightwave Finance ERP invoices the partners Recipients day-before texts one backfill, after the load open ones only, as normal The load's real size is every record times everything each record sets off. Keep only the outcomes you need. HOW TO READ IT the load © 2026 Twinshark LLC · stevetecharc.com
คลิกเพื่อขยาย

Keep only the outcomes you need: one backfill, texts for the open deliveries, nothing to partners or finance. ⟲

ผลข้างเคียงภายนอกแย่กว่า อีเมลถึงลูกค้า คำขอเรียกเก็บเงิน event ที่ระบบ production บริโภค การเรียก ERP ตั๋วสนับสนุน การอัปเดตด้านการตลาด: ระบบเหล่านั้นไม่รู้ว่าเป็นข้อมูลการย้าย และเมื่อข้อความออกจาก Salesforce ไปแล้ว การย้อนกลับอาจเป็นไปไม่ได้ บทที่ 9 ให้สัญญาข้อมูลการผสานรวมแก่เรา ระหว่างวางแผนการย้ายข้อมูล ให้ตัดสินว่าลูกศรไหนทำงานได้ ไหนถูกระงับ และไหนถูกแทนด้วยการซิงก์หลังสลับระบบ การตัดสินใจนั้นควรอยู่ในแผนการสลับระบบ

ข้อมูลที่คำนวณได้ การแชร์ และออบเจกต์พักข้อมูล

หัวข้อที่มีชื่อว่า “ข้อมูลที่คำนวณได้ การแชร์ และออบเจกต์พักข้อมูล ”

roll-up และค่าที่คำนวณได้อื่นๆ: โหลดเรกคอร์ดแม่ แล้วเรกคอร์ดลูกหลายล้าน แล้วคำนวณใหม่หลังเรกคอร์ดลูกทุกตัว? อาจได้ แต่บ่อยครั้งการโหลดทุกอย่างแล้วคำนวณครั้งเดียวถูกกว่ามาก คำถามคือผลลัพธ์ที่คำนวณได้ต้องถูกรักษาไว้ทีละเรกคอร์ดระหว่างการย้ายข้อมูล หรือสร้างขึ้นหลังจากข้อมูลที่ขึ้นต่อกันครบแล้วได้ นั่นคือการตัดสินใจแบบไม่ต้องใช้ / จำลอง / เลื่อน แบบเดิม

การแชร์ก็เป็นข้อมูลที่คำนวณได้เช่นกัน การสร้างและการโอนเรกคอร์ดกระตุ้นการคำนวณกฎการแชร์ และในการโหลดขนาดใหญ่ นั่นอาจหมายถึงการประเมินที่ยาวมากหรือหมดเวลา Salesforce ให้ผู้ดูแลเลื่อนการคำนวณการแชร์ (กฎการแชร์และการเป็นสมาชิกกลุ่ม) แล้วกลับมาทำต่อทีหลังได้ แต่ฟีเจอร์นี้ไม่ได้เปิดเป็นค่าเริ่มต้น: ฝ่ายสนับสนุนของ Salesforce เป็นผู้เปิด เมื่อทำต่อ คุณต้องรันการคำนวณใหม่ทั้งหมด และการเปลี่ยนแปลงการแชร์บางอย่างยังถูกคำนวณทันทีเพื่อปกป้องความสมบูรณ์ของข้อมูล (Defer Sharing Calculations (เปิดในแท็บใหม่)) วางแผนมัน และวางแผนเวลาของการคำนวณใหม่

Deferring has limits of its own. The catch-up usually runs as batch Apex, and that shares the org’s daily allowance of asynchronous Apex executions: “250,000 or the number of applicable user licenses in your org multiplied by 200, whichever is greater.” Only five batch jobs can be queued or active at once, with up to 100 more waiting in the flex queue (Execution Governors and Limits (เปิดในแท็บใหม่), Apex Developer Guide, Winter ‘27, checked 2026-10-27). Your catch-up competes with every other batch job in the org, so schedule it, and size it. ⟲

Test knowledge. Large loads trigger sharing recalculation. Salesforce Support can enable deferred sharing calculations (sharing rules and group membership), which you resume and recalculate after the load. Deferred work usually runs as batch Apex, within the daily asynchronous Apex limit and five concurrent batch jobs. ⟲

And sometimes the logic you need is simply too slow to load through. This is the special case module 1 mentioned. A process that takes a second or two per record is fine for users; for hundreds of thousands of records in a cutover window it means days, and trying to simulate an intricate object model in the load can mean a dozen tables. The technique I use: load into a staging object first, a light custom object with no automation that holds the import fields and lookups, then let a batch process work through it, calling the platform’s own logic to build the real records. The status on each staging row lets the batch work in chunks, pause and resume, and the original import fields stay alongside the records they created for tracing. You get the data in fast and catch up on the processing afterward. ⟲

เป้าหมายไม่ใช่ “รันระบบอัตโนมัติของ production” แต่คือไปถึงสถานะ production ที่ถูกต้อง และสองอย่างนี้ไม่เหมือนกัน การประมวลผลปกติสำหรับบัญชีใหม่คำนวณการจัดประเภท สร้างงานต้อนรับ ส่งการแจ้งเตือน และเผยแพร่ไปยังอีกระบบ สำหรับบัญชีประวัติที่ย้ายมา สถานะสุดท้ายที่ถูกต้องอาจเป็น: การจัดประเภทใช่ งานต้อนรับไม่ การแจ้งเตือนต้อนรับไม่ การเผยแพร่ออกภายนอกอาจใช่ ขึ้นกับแผนการซิงก์ การรันระบบอัตโนมัติปกติแบบไม่ลืมหูลืมตาคือการทำซ้ำกระบวนการที่ไม่ได้ออกแบบมาสำหรับการย้ายข้อมูล

สำหรับการย้ายข้อมูลที่จริงจัง ให้เขียนเป็นรายการระบบอัตโนมัติ:

ระบบอัตโนมัติพฤติกรรมปกติการตัดสินใจสำหรับการย้ายข้อมูลผลลัพธ์ที่ต้องได้จากการย้ายข้อมูล
Status out to partnersSend each status change to Redrock, Keystone, BrightwaveDon’t need itNone: the partners already have it
Change Data Capture to SnowflakeA change event per Work OrderDeferOne backfill of status history after the load
Delivery counts to financeCount each completed delivery for invoicingDon’t need itNone: already invoiced; reconcile the count instead
Day-before textText the Recipient with a tracking linkRun deliberately, open deliveries onlyMonday’s Recipients get the link; none for delivered ones
Work Order statusSet by the crews’ appSimulateStatus mapped in the preparation data store
Install checklist and photos (R12)Block closing an install without themBypass for the migration identityCompleted installs load as completed; no invented photos
Every Work Order has a partnerReject a Work Order without oneKeepMissing partner: quarantined before the load

ตอนนี้การตัดสินใจมองเห็นได้: เราทบทวนได้ ทดสอบได้ ซ้อมได้ และตรวจยืนยันหลังการโหลดได้

อย่าให้ production เป็นครั้งแรกที่คุณใช้โหมดการย้ายข้อมูล การซ้อมควรทดสอบตัวตนสำหรับการย้ายข้อมูล การควบคุมทางเลี่ยง ระบบอัตโนมัติที่ยังทำงาน ผลลัพธ์ที่จำลอง กระบวนการที่เลื่อนไว้ และการกลับสู่โหมดปกติ แล้วเช็ก: มีอะไรทำงานที่ไม่ควรทำงานไหม มีอะไรไม่เกิดที่ควรเกิดไหม สถานะสุดท้ายตรงกับสถาปัตยกรรมไหม? นั่นคือเหตุผลที่การซ้อมต้องใช้การตั้งค่าระบบอัตโนมัติจริง หรือใกล้เคียงที่สุดเท่าที่ทำได้

การเปิดกลับคือขั้นตอนหนึ่งของการสลับระบบ: ชัดเจน มีเจ้าของระบุชื่อ เวลาที่คาด และการตรวจยืนยัน ไม่ใช่ “อย่าลืมเปิด flow กลับนะ” ระบบยังไม่พร้อมสำหรับผู้ใช้จนกว่าการทำงานปกติจะถูกกู้คืนและตรวจยืนยันแล้ว (โมดูลที่ 4 ใส่ไว้ใน runbook)

And beware the catch-up storm. We suppressed downstream synchronization while loading RouteDesk’s records; now we switch the integration back on. Does it see five million “new” records and try to send them all? Maybe the downstream system already received them another way, maybe only changes after the cutover watermark should go, maybe it needs a controlled initial sync. The automation decision and the integration decision have to work together. Turning automation back on isn’t enough: know what it will do when it wakes up. For Steve Trucking, the status flows and the Change Data Capture subscriber should see only the changes made after cutover, never the weekend’s load. ⟲

ทีนี้เพิ่มเอเจนต์ที่ตอบสนองต่อเคสใหม่ บัญชีที่เปลี่ยน event ที่ถูกเผยแพร่ หรืองานในคิว การย้ายข้อมูลสร้างแพตเทิร์นข้อมูลในระดับเครื่องจักร เราอยากให้เอเจนต์ตอบสนองต่อทุกเรกคอร์ดที่ย้ายมาไหม? คงไม่ ถ้าเกิดโดยบังเอิญ กระบวนการที่เอเจนต์กระตุ้นควรอยู่ในรายการเดียวกับ flow, trigger การแจ้งเตือน การผสานรวม และ event และถ้าบริบทการย้ายข้อมูลควรระงับมัน ก็ออกแบบสิ่งนั้นอย่างตั้งใจ

นอกเหนือจากการสอบ: AI เปลี่ยนอะไร เอเจนต์คือผลข้างเคียงอีกแบบ แบบที่อาจตอบสนองต่อข้อมูลที่ย้ายมาด้วยตัวเอง ปฏิบัติต่อการกระทำที่เอเจนต์กระตุ้นเหมือนระบบอัตโนมัติอื่นๆ: ตัดสินว่าจะรัน จำลอง เลื่อน หรือระงับ และทดสอบการตัดสินใจนั้นในการซ้อม

  • ระบบอัตโนมัติไหนทำงาน ไม่ต้องใช้ ถูกจำลอง หรือถูกเลื่อน สำหรับข้อมูลที่ย้ายแต่ละประเภท โดยรู้ว่าการปิดตัวหนึ่งหมายถึงการเป็นเจ้าของตรรกะทางธุรกิจของมัน
  • กฎการตรวจสอบความถูกต้องไหนแทนความจริงของข้อมูลที่ยั่งยืน และไหนเป็นกฎของกระบวนการปัจจุบันที่ต้องจัดการเฉพาะสำหรับการย้ายข้อมูล
  • How scoped bypasses are designed into every automation from the start, tested on and off, and deployed long before they’re needed, without an unrestricted “skip everything” path. ⟲
  • ข้อมูลที่คำนวณได้ การคำนวณการแชร์ใหม่ และตรรกะของแพลตฟอร์มที่ช้า ถูกจัดการอย่างไร: หลังการโหลด เลื่อนไป หรือผ่านออบเจกต์พักข้อมูล
  • ผลข้างเคียงภายนอกและการผสานรวมไหนถูกระงับหรือตามเก็บอย่างตั้งใจ และการซ้อมกับการสลับระบบพิสูจน์อย่างไรว่าระบบอัตโนมัติปกติถูกกู้คืนอย่างปลอดภัย

การย้ายข้อมูลไม่ได้สำเร็จเพราะ flow ทุกตัวรัน trigger ทุกตัวทำงาน และกฎการตรวจสอบความถูกต้องทุกข้อถูกประเมิน นั่นคือพฤติกรรมธุรกรรมปกติ และการย้ายข้อมูลมีงานอีกแบบ: ย้ายข้อมูลเข้าสู่สถาปัตยกรรมใหม่ รักษาความจริงที่สำคัญ สร้างค่าที่คำนวณได้ที่เราต้องการ หลีกเลี่ยงผลข้างเคียงที่ผิด รักษาระบบให้ควบคุมได้ แล้วคืนมันสู่ภาวะปกติ สำหรับระบบอัตโนมัติแต่ละตัว: ไม่ต้องใช้ จำลองมัน เลื่อนมัน หรือจงใจปล่อยให้มันทำงาน แต่ทำให้มันเป็นการตัดสินใจ อย่าให้ห้าล้านเรกคอร์ดตัดสินใจแทนคุณ