Bulk vs real-time processing in workflow automation

I’ve been designing workflow automation solutions in Salesforce for 5 years now, and one pattern I see teams struggle with repeatedly is choosing between bulk and real-time processing approaches. There’s no one-size-fits-all answer, but I wanted to share some experiences and get perspectives from others.

Real-time workflows (immediate Process Builder/Flow triggers) are intuitive and provide instant feedback, but they hit governor limits quickly with bulk operations. Bulk processing (scheduled flows, batch Apex) handles volume well but introduces latency that some business processes can’t tolerate. The hybrid approach - using real-time for critical paths and bulk for everything else - seems ideal but adds complexity.

I recently worked with a client who had 15 different real-time flows triggering on Account updates. When they did a data migration of 50,000 accounts, everything timed out. We redesigned using a hybrid model: immediate flows only for user-facing updates, scheduled flows for batch processing, and platform events to coordinate between them. System load dropped by 70% and user experience actually improved.

What strategies have others used for balancing real-time responsiveness with governor limit constraints? How do you decide which processes should be real-time vs batch?

Bulk vs. Real-Time: Architecture Decisions and Migration Path

Your hybrid model is the right direction. The 15-concurrent-flow problem on Account updates is a classic DML row lock and CPU limit exhaustion pattern — not a Flow design failure, but an architecture mismatch between trigger strategy and data volume expectations.


Pre-Upgrade Checks (Before Restructuring Existing Automation)

  • Audit active automation inventory: Run Setup > Flows and query FlowDefinition + FlowVersionView via Tooling API to enumerate all active record-triggered flows, Process Builder processes, and Workflow Rules on the target object.
  • Identify governor limit hotspots: Enable Flow Interview Logs and review Debug Logs at APEX_CODE, DEBUG level during a controlled bulk operation. Look for LIMIT_USAGE_FOR_NS entries exceeding 80% thresholds on CPU time, DML statements, and SOQL queries.
  • Map cross-object dependencies: Any flow traversing parent/child relationships in bulk context is a candidate for bulkification failure. Document all Get Records elements that lack explicit collection handling.
  • Catalog Platform Event consumers: If you’re introducing Platform Events as coordination layer (as you did), verify existing trigger frameworks won’t create duplicate processing. Check EventBusSubscriber object via SOQL (verify in your version).
  • Backup and version: Ensure all flows are saved with meaningful version descriptions before restructuring. There’s no native diff tool — treat this like code.

Decision Framework: Real-Time vs. Batch

The architectural decision reduces to three variables: user visibility, downstream dependency latency tolerance, and expected DML volume per transaction.

Trigger Type Use When
Record-triggered Flow (fast field updates) User-initiated, <200 records, immediate UI feedback required
Record-triggered Flow (after save, async) Audit logging, notifications — decoupled from user wait time
Platform Events Cross-object coordination, external system signaling, decoupled retry logic
Scheduled Flow Nightly recalculations, SLA monitoring, anything tolerating minutes of latency
Batch Apex >10,000 records, complex aggregation, custom retry/error handling requirements

Numbered Migration Sequence

  1. Freeze automation changes on the target object in your change management process.
  2. Deactivate redundant real-time flows — consolidate to a single entry-point flow per object per trigger event (before/after save). Multi-flow fan-out on the same object is the primary governor exhaustion cause.
  3. Implement bulkification gates: Add a $Record collection check or use the isChanged() function to prevent unnecessary execution paths in bulk context (verify in your version for collection-aware syntax).
  4. Publish Platform Events from the entry-point flow for processes that don’t require synchronous completion.
  5. Deploy Scheduled Flows or Batch Apex as Platform Event consumers or independent scheduled jobs.
  6. Load-test with representative volume: Use Data Loader at 200-record batch size (default API batch) to simulate migration conditions before go-live.
  7. Enable Flow Bulk Processing on record-triggered flows where available — this allows Flow to respect DML bulkification patterns natively (verify in your version).

Rollback Procedure

  • Maintain version-numbered Flow backups before each deactivation. Reactivating a prior version is the fastest rollback path.
  • Keep deactivated Process Builder processes intact for 30 days post-migration — reactivation is immediate if regression is detected.
  • If Platform Event consumers are misbehaving, pause the Event Relay or adjust ResumeCheckpoint on EventBusSubscriber rather than full rollback.
  • Document the original 15-flow architecture in a sandbox org as a restore baseline.

The 70% load reduction you saw is consistent with eliminating redundant re-entry and unnecessary SOQL inside looped flow elements. The Platform Event layer also provides natural backpressure that synchronous chains can’t offer.


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

Great topic. My rule of thumb: if a user is waiting for the result, make it real-time. If it’s background processing that doesn’t need immediate visibility, use batch. The hybrid approach you mentioned is exactly right but requires careful planning. We use platform events as a queue - real-time flows publish events for non-critical updates, and a scheduled flow processes the event queue every 15 minutes. This decouples the user experience from heavy processing.

Governor limits are the forcing function here. I’ve seen too many orgs hit the 2000 DML limit or 50,000 SOQL row limit because everything runs real-time. For high-volume operations like lead assignment, opportunity scoring, or data enrichment, batch processing is non-negotiable. The latency trade-off is worth it when the alternative is system failures. We typically set real-time thresholds - if an operation might affect more than 100 records, route it to batch processing automatically using record count checks in flows.

The hybrid strategy works well but communication with stakeholders is crucial. Business users expect real-time everything, so you need to educate them on why some processes run in batch mode. We create visibility into batch processing status using custom notifications and dashboard widgets showing queue depth and processing times. This transparency helps users understand that ‘not instant’ doesn’t mean ‘not working’. Most business processes can tolerate 5-15 minute delays if they know when to expect results.

One pattern I’ve found effective: use real-time flows for validation and routing, but delegate heavy processing to queueable Apex or platform events. For example, when an opportunity closes, the real-time flow validates required fields and updates the stage immediately (user sees instant feedback), but spawns a queueable job to handle contract generation, provisioning notifications, and integration callouts. This gives the illusion of real-time processing while actually deferring the expensive operations. Users get immediate confirmation, background jobs handle the complexity.

External integrations complicate this significantly. Real-time flows that make callouts can timeout or fail if external systems are slow. We learned this the hard way when our real-time order processing flow called an inventory system that sometimes took 10+ seconds to respond. Switched to a pattern where the real-time flow creates a platform event, and a separate queueable process handles the external callout with proper retry logic. This isolates user transactions from external system performance issues.

I’ve implemented both approaches across dozens of Salesforce orgs, and the decision framework comes down to three dimensions: user experience requirements, data volume patterns, and system complexity tolerance.

Bulk vs Real-Time Flow Design:

Real-time flows excel when:

  • Users need immediate visual feedback (status changes, field updates they can see)
  • Volume is predictable and moderate (under 100 records per transaction typically)
  • Business logic is simple and executes quickly (under 1 second)
  • The operation is part of an interactive user workflow

Bulk processing (scheduled flows, batch Apex) is necessary when:

  • Operations affect hundreds or thousands of records
  • Processing involves complex calculations or multiple object updates
  • External system integrations with variable response times
  • The operation can tolerate 5-30 minute delays

The key insight: most organizations need both. The mistake is trying to make everything real-time or everything batch. Design for the actual business requirements, not the technically easiest approach.

Governor Limit Management:

Governor limits force architectural decisions. Here’s how I structure workflows to stay within limits:

For real-time flows, implement ‘escape valves’ - if the operation might affect more than a threshold number of records, route to batch processing instead. Use a decision element in your flow:


IF RecordCount > 100 THEN
  Create Platform Event for batch processing
ELSE
  Process immediately
END IF

This hybrid routing prevents governor limit exceptions while maintaining real-time processing for normal operations. Monitor your governor limit consumption through Event Monitoring or custom logging to tune these thresholds.

Batch processing requires different patterns:

  • Chunk large operations into manageable batch sizes (100-200 records per batch is optimal)
  • Implement checkpointing for long-running processes so failures don’t require complete reruns
  • Use platform events to coordinate between batch jobs when dependencies exist
  • Schedule batch jobs during off-peak hours to reduce resource contention

Hybrid Workflow Strategies:

The most effective pattern I’ve deployed is the ‘fast path / slow path’ architecture:

Fast Path (Real-Time):

  • User-visible field updates
  • Simple validations and business rules
  • Critical path operations that block user workflow
  • Lightweight integrations with guaranteed fast response

Slow Path (Batch/Async):

  • Complex calculations and aggregations
  • Multi-object cascading updates
  • External system integrations
  • Non-critical enrichment and scoring

Implementation using Platform Events:

  1. Real-time flow handles fast path operations immediately
  2. Real-time flow publishes platform event with context data for slow path
  3. Event-triggered flow or queueable Apex processes slow path asynchronously
  4. Completion notification updates original record or sends user notification

This architecture provides the best of both worlds - users get immediate feedback for critical operations, while complex processing happens in the background without impacting their experience.

For your specific example with 15 flows on Account, consolidate into a single orchestration flow that:

  • Evaluates which logic paths are needed based on what changed
  • Executes critical updates immediately
  • Queues non-critical updates via platform events
  • Monitors execution metrics to optimize the fast/slow path boundary

This reduced your system load by 70% because you eliminated redundant trigger executions and deferred non-critical processing.

Decision Framework:

When designing a new workflow, ask:

  1. Does a user need to see the result before proceeding? → Real-time
  2. Could this operation affect more than 100 records? → Batch
  3. Does it involve external systems? → Async/Batch
  4. Is it triggered by user action or system event? → User=Real-time, System=Batch
  5. What’s the acceptable latency? <5sec=Real-time, >5min=Batch

The answer is usually a hybrid: immediate validation and critical updates in real-time, with heavy processing and integrations deferred to batch. This balances user experience with system scalability and stays within governor limits even at high volume.