Failures and what happens if…
Retries, dead events, what the Errors page shows, and the order events run in.
Failures
Every trigger is stored as a durable event before any action runs. An event is
queued, then running, then done. A failure retries
after 1 minute, 5 minutes, 30 minutes, 2 hours, 8 hours and 16 hours, seven attempts in
all, and then the event is dead.
You receive the relay_failed alert, on by default and switchable on
Settings → Notifications, and the event's replay button resets the count. A definition-level failure,
such as a suspended person, a missing collection or an unknown
entitlement, is dead on the first attempt.
Actions run in order and stop at the first failure. A retry skips the actions that
already succeeded and continues from the one that failed. A replay, or a retry after the
relay was edited, runs every action again: write_record,
grant_access, revoke_access and email_person each
find their own earlier work and record skipped; call_url POSTs
again. Every run is one audit entry with each action's before and after, and every grant,
email and record a relay makes is attributed to it by name.
A paused relay still records receiver events and record changes; they wait for resume. Schedule ticks during a pause are not recorded. Events are kept for 30 days.
What the Errors page shows for relays
When events wait longer than they should, the dashboard's Errors page says so, in the
environment it happened in, with a sentence naming the relay. relays_delayed is
raised in Live only. No event is dropped in any of the three.
| Code | What it means | What to do |
|---|---|---|
relays_delayed | In Live, a relay's events waited more than 30 seconds to run. The sentence says how long and how many are waiting, and whether your own relays were already running at their limit. They are kept and run in order | Nothing: they run in order as the earlier ones finish. When it was not your own load, Gemmein's operators are alerted too |
relays_held | An event waited more than 60 seconds behind an earlier event for the same record or person, which runs first. The sentence names the relay it waits behind and why: paused, retrying a failed run, still running, or not run yet | Resume the paused relay, or fix and replay the failing one; the waiting event runs next |
relays_dev_capped | Development passed its hourly limit of immediate relay runs: 120 per app, 300 per account. The rest wait their turn and run within minutes | For volume, run your app on npx gemmein dev. Live has no such limit |
What happens if…
A relay with an action that grants or takes what a person holds
(grant_access, revoke_access, grant_credits,
fulfil_product, refund_product, grant_plan,
revoke_plan) is a payment relay, including one that also has
start_run. Every other relay, including one whose only action is
start_run, is an ordinary relay.
| If… | What happens | What you do |
|---|---|---|
| An event arrives in Live | A receiver, record-change, run-started or credits-low relay runs within seconds. A receiver answers the provider first, then runs. A schedule runs on its tick | Nothing |
| An event arrives in Development | Relays run at once up to 1 run per app at a time, 120 runs per app and 300 per account an hour. Past that, events wait their turn and run within minutes; none is dropped, and the Errors page says the limit was reached | For volume, run your app on npx gemmein dev |
| One customer, several payment events | Payment events from your provider (receiver relays) for one customer run one at a time, in the order the payments happened, across all payment relays: the mapped paid_at (a time later than the event's arrival counts as its arrival), else when the event arrived. A payment relay's event runs 2 seconds after it arrives, so an event sent a moment earlier lands first | Map paid_at whenever the provider sends a payment time |
| A refund arrives while its payment is still running or retrying | The refund waits, and runs once the payment succeeds or is dead | Nothing |
| Ordinary relays, record changes, run starts, credits running low | Events run in order only within the relay itself: one record's changes, or one person's events. They never wait for another relay | Nothing |
| A payment relay is paused | That customer's later events on payment relays wait. After 60 seconds the Errors page names the relay they wait on | Resume the relay, and they run |
A relay whose only action is start_run is retrying | It never holds a payment relay, and never waits for one. A relay with start_run plus a grant or take action is a payment relay | Nothing |
| You edit a relay while an event waits to retry | A retry runs the relay as it is now. A grant or take already done for that event is never repeated. Changing which product or access a grant gives counts as a new grant; changing a plan or credit amount applies to new events only. call_url can receive the event again | Deduplicate on the event's id at your URL |
| A relay has two grant or take actions on the same target | The save is refused with duplicate_grant_target, naming the action and its target. A relay grants or takes each target once: one per product, access key or plan, and one grant_credits | Merge the two into one action; for credits, one grant_credits with the summed amount |
| A retry with no edit | It skips the steps that already succeeded and continues from the one that failed | Nothing |
| You add or remove a grant or take action | The relay becomes a payment relay, or stops being one; events already waiting follow the change when it is saved | Nothing |
| A deploy or restart | Unfinished runs go back to the queue and finished steps do not repeat. A call_url that was in flight can arrive twice | Deduplicate on the event's id |
No paid_at in the map | A payment for an address whose owner deleted their account grants nothing and shows on the Errors page | Map paid_at; refund or grant by hand from the Errors page |
Thanks for telling us.
Thanks for telling us.
Last updated