Events
How every Action writes immutable Events to one ordered log, and how Triggers, Watches and webhooks react to them.
An Event is the immutable record that something happened, named Noun.pastTense, such as Order.paid. Every Action writes Events, and Events start every Workflow, Metric and outbound delivery.
One log per namespace
Each Startup has one ordered Event log in db.sb. An Action appends an Event on every status change, from pending to done, failed, canceled or refused. Model calls, inbound webhooks and Visits land in the same log, in the same order.
The log keeps everything forever. No Event expires and none is deleted; a correction is a new Event that supersedes the old one. Current state is therefore always explainable: every field of every Thing traces to the Events that set it.
Names
An Event's name comes from its Verb. The Verb pay on an Order emits Order.paid; staff on a Role emits Role.staffed. Inherited writes emit created, updated and deleted.
| Verb | Event | Payload |
|---|---|---|
| publish | Offer.published | The Offer |
| pay | Order.paid | The Order |
| answer | Conversation.answered | The Conversation |
| register | Domain.registered | The Domain |
The registry derives every name, so an Event never drifts from the Verb that emits it. The Event reference lists all of them.
Selectors
One grammar matches Events everywhere: a name, an optional where clause, and bindings. Triggers, Meters, Watches and Tasks that close on an Event all use it.
const bigOrders = {
event: 'Order.paid',
where: { 'order.total.amount': { gte: 1000 } },
}A selector reads the Event payload, so order.total.amount is the paid Order's total.
Triggers
A Trigger starts a Workflow on an Event, a schedule, or a Thing entering a state. Triggers are records, so a Startup's whole reactive behavior is a query away.
import { $ } from 'startup-builder'
// The deliver-outcome Workflow starts on this Trigger.
await $.Trigger.create({ event: 'Order.paid' })Every Trigger firing is itself an Action, with its own Events. A Workflow that fails leaves a failed Action and the Event that caused it, side by side.
Watches and webhooks
A Watch delivers matching Events to an outside URL. Each delivery is signed, retried with backoff, and replayable from any point with replay.
Add a watch to ShiftNote.
curl -X POST https: //api.sb/ shiftnote.app/ watches \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/ json" \
-d '{"selector": "Example selector", "url": "https: //shiftnote.app"}'
import { $ } from 'startup-builder'
const { watch, secret } = await $.Watch.create({ selector: 'Example selector', url: 'https: //shiftnote.app' })
npx startup-builder do Watch.create --json '{"selector": "Example selector", "url": "https: //shiftnote.app"}'
{
"name": "do",
"arguments": {
"code": "return await $.Watch.create({ selector: 'Example selector', url: 'https: //shiftnote.app' })"
}
}
Inbound webhooks enter through one ingress per Startup. The ingress verifies the sender's signature, writes an Event, and hands it to Triggers. A signal from an Integration is therefore handled like an internal one.
| Term | Kind | Definition |
|---|---|---|
| Action | Noun | An Action is one Verb performed by a Worker on a Thing, recorded with its status and every Event it emits. |
| Event | Noun | An Event is the immutable record of something that happened to a Thing, named by its Noun and past-tense Verb. |
| Trigger | Noun | A Trigger is what starts a Workflow: an Event, a schedule, or a Thing entering a state. |
| Watch | Noun | A Watch is an outbound subscription that delivers the Events a selector matches to a URL, signed, retried, and replayable. |
| Watch.pause | Verb | Pause stops a Watch delivering while its Events keep queuing; the platform pauses a Watch whose deliveries fail for three days. |
| Watch.replay | Verb | Replay redelivers a Watch’s Events from a chosen point, signed as they were the first time. |
| Watch.resume | Verb | Resume restarts a paused Watch and delivers the Events it held, oldest first. |
| Watch.rotate | Verb | Rotate issues a new signing secret for a Watch and signs with both secrets until the old one expires. |
Next
- Event reference: every Event and the Verb that emits it.
- Integrations: outside Sources that send and receive Events.
- Analytics: Metrics computed from Events.