Platform: Infosys Equinox | EventBridge Source:
"foundation-service"
EventBridge bus: EVENT_BUS_NAME (default eq-9-sandbox1-eventbus) Publishing gate: the EventBridge plugin is registered with enabled: process.env.STAGE !== 'test' — i.e. events publish in every stage except test. (There is no ENABLE_EVENT_BRIDGE variable; an older stub path uses ENABLE_EVENT_PUBLISHING — see “Legacy / stub publisher” below.)
What Are Events and Why Do They Matter
When Foundation changes certain entities, it publishes a domain event to AWS EventBridge. Other microservices subscribe to these events to react in real time without polling Foundation. For example, a downstream changelog/indexer service consumes foundationservice/store/create to keep its own copy of store data current.
If publishing is disabled (e.g. STAGE=test), the mutation still succeeds — the event is simply skipped and logged.
How Events Are Actually Published
Foundation publishes through the @equinox/event-bridge-implementation Fastify plugin, registered in src/app.ts with source: 'foundation-service'. Service-layer code calls the decorator fastify.publishEvent({ type, subject, data }).
Real example — store creation (src/service/store.service.ts):
await fastify.publishEvent({
type: 'foundationservice/store/create',
subject: `store-${savedStore.storeId}`,
data: {
id: savedStore.storeId,
collectionId: savedStore.businessId, // NOTE: businessId, not instanceId
userId: savedStore.createdBy || userId,
traceId: fastify.requestId || 'system',
properties: ['storeId', 'name', 'businessId', 'status', 'type', 'defaultLocale', 'defaultCurrency'],
payload: savedStore // the full entity document
}
});
Event detail shape
The plugin wraps the call and delivers a detail of the form:
{
"data": {
"id": "<entity id>",
"collectionId": "<owning businessId>",
"userId": "<acting user id>",
"traceId": "<request id or 'system'>",
"properties": ["<changed/relevant field names>"],
"payload": { "<full entity document>" }
},
"eventMetadata": { "<plugin-added metadata>" }
}
There is no
entityType,eventType,instanceId,entity, orbeforeStatefield on domain events. Domain events carrycollectionId(= the owningbusinessId), notinstanceId. Only batch events (published a different way, see below) carryinstanceId.
Published Events (Outbound)
Only four entity domains actually publish publishEvent domain events today: store, location, locationEvent, and batch. Other entities (business, site, seller, siteData, storeAssociation, serviceProperty, featureFlag, userPreset) do not currently emit events.
Store events
type string |
Trigger |
|---|---|
foundationservice/store/create |
Store created |
foundationservice/store/update |
Store replaced (PUT) |
foundationservice/store/patch |
Store patched (PATCH) |
foundationservice/store/delete |
Store soft-deleted |
Location & Location Event
type string |
Trigger |
|---|---|
foundationservice/location/create |
Location created |
foundationservice/location/updated |
Location updated (PUT or PATCH) |
foundationservice/location/deleted |
Location soft-deleted |
foundationservice/location/property-update |
Single location property upserted |
foundationservice/location/property-delete |
Single location property deleted |
foundationservice/location/properties-replace |
All location properties replaced |
foundationservice/location/properties-patch |
Location properties merge-patched |
foundationservice/location/bulk-sfs-update |
Bulk ship-from-store flag toggle |
foundationservice/location/association-properties-update |
Location association properties updated |
foundationservice/location-event/create |
Location event created |
foundationservice/locationEvent/updated |
Location event updated |
foundationservice/locationEvent/deleted |
Location event deleted |
Batch execution events
Published from the batch execution service (src/service/batchExecution.service.ts):
type string |
Trigger |
|---|---|
batch.execution.completed |
Execution finished successfully |
batch.execution.partial_success |
Execution finished with some failed records |
batch.execution.failed |
Execution failed |
batch.execution.stopped |
Execution manually stopped |
batch.execution.threshold_exceeded |
Error threshold exceeded mid-run |
batch.execution.retry_requested |
A retry was requested |
batch.execution.retry_started |
Retry execution started |
batch.execution.retry_failed |
Retry execution failed |
batch.execution.max_retries_exhausted |
All retries exhausted |
Batch events use a second publish path. They are sent directly via the AWS SDK
PutEventsinsrc/lambda.ts, producing a flatDetail: JSON.stringify({ ...detail, timestamp })withSource: 'foundation-service'. These events do carryinstanceId.
Consumed Events (Inbound)
Inbound events are routed by the switch in src/handlers/batchEventHandler.ts (and dispatched from src/lambda.ts).
Active handlers
| Detail Type | Purpose |
|---|---|
batch.execution.progress |
Update the execution’s progressPercent |
batch.execution.completed |
Mark execution COMPLETED, record metrics |
batch.execution.failed |
Mark execution FAILED, record error |
batch.execution.retry_requested |
Trigger a retry of a failed execution |
batch.schedule.trigger |
Fire a scheduled batch job (from the EventBridge cron rule) |
batch.job.initiated |
Begin processing an initiated job |
batch.job.started |
Mark the job as started/running |
gdpr.export.* / gdpr.delete.* |
GDPR Step Functions action routing (see 15-gdpr.md) |
Deprecated handlers (backward-compatibility only)
These are still accepted but are marked deprecated in code — do not build new integrations against them:
batch.job.completed, batch.job.failed, batch.chunk.completed, batch.chunk.failed
Loop prevention: the EventBridge rule that targets Foundation’s handler filters by source so Foundation does not re-consume its own published events.
Legacy / stub publisher (not the live path)
The repository also contains src/utils/eventPublisher.ts (EventBridgeEventPublisher with publishCreated/publishUpdated/publishDeleted and an EventPayload {entityType,eventType,instanceId,entity,userId,beforeState} interface) and src/utils/eventPublisher.util.ts (gated by ENABLE_EVENT_PUBLISHING, bus EVENTBRIDGE_BUS_NAME='foundation-events', with StoreCreationStarted/Completed/Failed stubs).
These are not wired into the live request path — they have no call sites in the service layer and are placeholder/TODO code. The envelope described in older documentation came from this dead path. The authoritative, live behaviour is the fastify.publishEvent(...) path described above.
Revision History
2026-08-04 | AN – Page created and uploaded the contents