platform-event-publish-patterns
Publishing Platform Events: EventBus.publish, PublishBehavior (PublishImmediately vs PublishAfterCommit), high-volume events, event allocation, publish failures, Change Data Capture comparison. NOT for subscribing/consuming (use platform-event-subscribe-patterns). NOT for CDC architecture (use cdc-patterns).
Best use case
platform-event-publish-patterns is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Publishing Platform Events: EventBus.publish, PublishBehavior (PublishImmediately vs PublishAfterCommit), high-volume events, event allocation, publish failures, Change Data Capture comparison. NOT for subscribing/consuming (use platform-event-subscribe-patterns). NOT for CDC architecture (use cdc-patterns).
Teams using platform-event-publish-patterns should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/platform-event-publish-patterns/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How platform-event-publish-patterns Compares
| Feature / Agent | platform-event-publish-patterns | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Publishing Platform Events: EventBus.publish, PublishBehavior (PublishImmediately vs PublishAfterCommit), high-volume events, event allocation, publish failures, Change Data Capture comparison. NOT for subscribing/consuming (use platform-event-subscribe-patterns). NOT for CDC architecture (use cdc-patterns).
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Platform Event Publish Patterns
Activate when emitting Platform Events from Apex, Flow, or external callers. Publish semantics have subtle implications: `PublishAfterCommit` vs `PublishImmediately` determines whether rollback erases the event, high-volume events consume monthly allocation, and publish failures surface differently from synchronous DML errors.
## Before Starting
- **Decide publish behavior.** `PublishAfterCommit` is the default and safest — event fires only if the surrounding transaction commits. `PublishImmediately` fires even if the transaction rolls back.
- **Check event allocation.** High-Volume events have daily + monthly caps per license.
- **Plan monitoring.** Publish failures return `SaveResult` errors; check every result.
## Core Concepts
### EventBus.publish
```
MyEvent__e evt = new MyEvent__e(Order_Id__c = oid, Amount__c = amt);
Database.SaveResult sr = EventBus.publish(evt);
if (!sr.isSuccess()) {
for (Database.Error err : sr.getErrors()) {
System.debug(err.getMessage());
}
}
```
Returns a `Database.SaveResult` per event, or `List<SaveResult>` for bulk.
### PublishBehavior
Set on event metadata (`PublishBehavior: PublishAfterCommit` | `PublishImmediately`):
- **PublishAfterCommit** (default): event fires only if the transaction commits. Safer; survives rollback.
- **PublishImmediately**: event fires regardless of transaction outcome. Use for telemetry where fire-and-forget is acceptable even on rollback.
### ReplayId and durability
Standard Platform Events are stored with a ReplayId; subscribers can replay from a specific Id (up to 72 hours). High-Volume events have different durability.
### Event allocation
Events are counted against an org's monthly Platform Event allocation (license-dependent). Bulk publishes consume one allocation unit per event published.
### Publishing from async contexts
Triggers, Queueables, Batch, Scheduled — all can publish. Publishing from a future method works but adds complexity; prefer publishing in the originating transaction.
## Common Patterns
### Pattern: Publish after DML commit
```
insert orders;
List<Order_Created__e> evts = new List<Order_Created__e>();
for (Order__c o : orders) evts.add(new Order_Created__e(Order_Id__c = o.Id));
EventBus.publish(evts); // fires after commit
```
### Pattern: Bulk publish with result check
```
List<SaveResult> results = EventBus.publish(events);
List<Id> failed = new List<Id>();
for (Integer i = 0; i < results.size(); i++) {
if (!results[i].isSuccess()) failed.add(events[i].someId__c);
}
```
### Pattern: Retry via Queueable
If `SaveResult` failure includes "STORAGE_LIMIT_EXCEEDED" or similar transient error, re-enqueue via Queueable with exponential backoff.
## Decision Guidance
| Scenario | PublishBehavior |
|---|---|
| Business-logic event — must not fire on rollback | PublishAfterCommit |
| Fire-and-forget telemetry | PublishImmediately |
| Chain to external system, must commit first | PublishAfterCommit |
| Alert/audit event, okay if tx rolled back | PublishImmediately |
## Recommended Workflow
1. Decide PublishBehavior on the event metadata.
2. Publish via `EventBus.publish(event)` or bulk list.
3. Always inspect `SaveResult` — publish is not guaranteed.
4. For business-critical events, pair with an outbox pattern (write to a custom object, async publisher retries on failure).
5. Monitor monthly allocation via Setup → Platform Events.
6. Test with `Test.startTest()` / `Test.getEventBus().deliver()` to drive subscribers.
7. Document event schema, versioning strategy, and retry guarantees.
## Review Checklist
- [ ] PublishBehavior set intentionally on metadata
- [ ] SaveResult inspected; failures logged or retried
- [ ] Event volume estimated vs allocation
- [ ] Bulk publish used for multi-event scenarios
- [ ] No silent ignore of failures
- [ ] Test uses `Test.getEventBus().deliver()` where needed
- [ ] Outbox pattern considered for business-critical events
- [ ] Event schema versioning plan documented
## Salesforce-Specific Gotchas
1. **`PublishAfterCommit` events do NOT fire in test context without `Test.getEventBus().deliver()`.** Tests silently pass while real subscribers wouldn't be invoked.
2. **Platform Events cannot be published from a transaction that's rolled back via `Database.rollback`** when behavior is PublishAfterCommit — no event fires. When PublishImmediately, the event fires even on rollback.
3. **Bulk publish allocates one event per record.** 200 events = 200 allocation units.
## Output Artifacts
| Artifact | Description |
|---|---|
| Event metadata spec | PublishBehavior + field list |
| Publisher Apex class | Bulk publish + SaveResult handling |
| Outbox pattern (optional) | Custom object + retry publisher |
| Monitoring dashboard | Allocation + failure metrics |
## Related Skills
- `integration/platform-event-subscribe-patterns` — consuming
- `integration/outbox-pattern` — durable publish
- `integration/cdc-patterns` — alternative for record changesRelated Skills
xss-and-injection-prevention
Use when writing or reviewing Visualforce pages, Apex controllers, or LWC components that output user-supplied data, build dynamic queries, or construct HTTP responses. Triggers: 'XSS in Visualforce', 'SOQL injection vulnerability', 'how to encode output in Apex', 'JSENCODE Visualforce', 'open redirect prevention'. NOT for Apex CRUD/FLS enforcement (use soql-security or apex-crud-and-fls), NOT for Shield encryption (use shield-encryption-key-management), NOT for AppExchange security review process (use secure-coding-review-checklist).
shield-event-log-retention-strategy
Use when designing Salesforce Shield Event Monitoring retention, SIEM routing, and storage-tier strategy — which event types to keep, for how long, where, and how to answer audit queries across hot/warm/cold tiers. Triggers: 'shield event log retention', 'route event monitoring to splunk', 'how long to keep login history', 'siem salesforce integration', 'event monitoring storage tier'. NOT for enabling Shield (see salesforce-shield-deployment).
recaptcha-and-bot-prevention
Use when configuring reCAPTCHA on Web-to-Case, Web-to-Lead, Experience Cloud forms, or Headless Identity flows, or when designing bot-mitigation strategies for Salesforce public-facing surfaces. Triggers: 'enable reCAPTCHA on Web-to-Case', 'bot spam submissions on my Experience Site', 'Headless Identity reCAPTCHA v3 setup'. NOT for AppExchange security review (use secure-coding-review-checklist), NOT for session-level login security policies (use session-management-and-timeout), NOT for IP-range-based access controls (use network-security-and-trusted-ips).
mfa-enforcement-patterns
Design MFA enforcement: auto-enablement, Salesforce Authenticator rollout, exceptions, service accounts, API-only users, SSO interop, and audit. Trigger keywords: MFA, multi-factor, two-factor, Salesforce Authenticator, MFA exception, MFA SSO, api-only MFA. Does NOT cover: end-user password policies, device-trust posture, or non-Salesforce IdP configuration.
event-monitoring
Shield Event Monitoring: event log types, downloading logs via REST API and SOQL, real-time event monitoring with streaming API, and threat detection policies. NOT for debug logs (use debug-logs-and-developer-console). NOT for custom platform event publishing/subscribing (use platform-events-apex).
encrypted-field-query-patterns
Design SOQL, filters, reporting, and indexes against Shield Platform Encryption fields. Trigger keywords: Shield Platform Encryption, encrypted field query, probabilistic vs deterministic encryption, encrypted SOQL filter, encrypted field index. Does NOT cover: Classic Encryption (deprecated), field-level security policy, or tenant secret key rotation.
apex-managed-sharing-patterns
Grant row-level access programmatically via __Share records when declarative sharing rules cannot express the policy. NOT for OWD, role hierarchy, or criteria-based sharing rule design.
omnistudio-testing-patterns
Use when testing or validating OmniStudio components — OmniScript preview, Integration Procedure step debugging, DataRaptor field-mapping validation, and end-to-end UTAM-based automation. NOT for Apex unit testing or standard Flow debugging.
omnistudio-error-handling-patterns
Use when designing fault behavior across Integration Procedures, DataRaptors, OmniScripts, and FlexCards — error routing, user-facing messaging, retry semantics, and idempotency. Triggers: 'omnistudio error', 'integration procedure fault', 'dataraptor error handling', 'omniscript retry', 'flexcard action failure'. NOT for general Apex exception design or Flow fault paths.
omnistudio-ci-cd-patterns
Use when designing or implementing CI/CD pipelines for OmniStudio components — DataPack export/import, versioning, environment promotion, and automated deployment. NOT for standard Salesforce metadata CI/CD or Apex-only pipelines.
omniscript-design-patterns
Use when designing or reviewing OmniScripts for guided experiences, step structure, branching, save/resume, and the boundary between OmniScript, Integration Procedures, DataRaptors, and custom LWCs. Triggers: 'omniscript design', 'too many steps in omniscript', 'save and resume omniscript', 'branching in omniscript', 'when should this be an integration procedure'. NOT for deep Integration Procedure or DataRaptor design when the guided interaction layer is not the main concern.
integration-procedure-cacheable-patterns
Use when designing Integration Procedures (IPs) with platform cache to cut latency and callout load. Covers cache key design, TTL selection, per-user vs org-wide partitions, invalidation on data changes, and safe fallback on cache miss/stale. Does NOT cover general IP authoring (see omnistudio-error-handling-patterns) or LWC client-side caching.