Multi-step and delays β
A one-action workflow is rarely interesting. The real value is sequencing β send a welcome message now, wait 3 days, check if they came back, send a follow-up, wait a week, hand off to a shepherd. Multi-step workflows do exactly that.

Sequential vs parallel β
Most workflows are sequential β action 1, then action 2, then action 3. You build them by connecting the bottom handle of one action to the top handle of the next.
When you need to run multiple branches at once (e.g. send WhatsApp and update a custom field at the same time), use a split node. Both branches start immediately when split is reached.
TIP
Splits eventually re-join through normal flow β there's no explicit "join" node. Each branch finishes independently.
Delays β
The wait_delay action pauses the run for a specified duration. Common patterns:
| Pattern | Why |
|---|---|
wait_delay 1 hour after welcome | Let the new member settle before the next message |
wait_delay 7 days for second touchpoint | Newcomer follow-up pacing |
wait_delay 30 days then check engagement | Discipleship milestone |
Delays are stored in the database, not held in memory β so a delay can be days or weeks long without consuming resources. When the delay elapses, the run picks up where it left off.
Wait-until β
For specific calendar moments (e.g. wait until the next Sunday 9 AM), use wait_until with a date expression. This is timezone-aware β it uses your church's timezone, not UTC.
A common use is welcome arrives Tuesday at 10 AM regardless of when they signed up, so members signing up on Saturday don't get a message in the middle of Sunday service.
Wait-event β
wait_event pauses until another event fires for the same subject. E.g. a workflow can wait for the next attendance.marked event for the member before continuing. Useful for "if they come back within 30 days, do X; otherwise do Y."
It also supports a timeout β if the event doesn't fire within the wait period, the run takes a fallback branch.
Conditional branching β
The condition action evaluates a boolean and routes to true / false. You can chain many conditions to build complex flows.
For multi-way branching (more than two outcomes), use split with conditions on each branch, or chain conditions in series.
Looping β
for_each iterates over a list. The list usually comes from a find_members_by_segment action earlier in the workflow.
Inside the loop, every action runs once per item. The current item is available as {{loop.current}} and the index as {{loop.index}}.
WARNING
Loops over very large segments (thousands of members) can take a while. Build in a small wait_delay between iterations to avoid rate-limiting your messaging providers.
FIFO ordering β
Within a single run, actions execute in graph order. Across runs, GCM processes them in FIFO order β first triggered, first run. There's no priority queue.
This matters when a high-volume trigger like attendance.marked fires for hundreds of members during a Sunday service: each member's workflow run is queued, and they process in the order the attendance was marked.
The async-vs-sync split β
GCM separates workflow runs into two execution paths:
- Synchronous β actions that complete in milliseconds (set variable, update member, condition). These run immediately when the action is reached.
- Asynchronous β actions that block (wait_delay, wait_event, send_message) or call slow external services. These get scheduled on a queue and resumed later.
You don't have to think about this β the builder handles it for you. But it's why a run with three wait_delay steps can sit for weeks without any active processing.
Worked example: welcome sequence β
A typical newcomer workflow:
- Trigger β
member.createdwhere membership type is Visitor. - Wait 1 hour.
- Send message β WhatsApp welcome.
- Wait 7 days.
- Condition β has the member attended any meeting since registration?
- True branch β send a "great to see you back" message.
- False branch β send an "invitation to join us this Sunday" message.
- Wait 30 days.
- Send notification β to the appropriate shepherd: "Time to follow up personally with this newcomer."
The whole thing takes about 5 minutes to build in the visual builder. See Newcomer follow-up workflow for the full walkthrough.
Resumability β
If GCM is restarted while a run is mid-execution, the run resumes where it left off β no actions get repeated, no actions get skipped. The state is persisted to the database at every step boundary.
Common questions β
Can a wait_delay last forever? The maximum is 365 days. For longer cycles, chain multiple workflows.
Can I edit a workflow while runs are in flight? Yes β the in-flight runs continue using the version they started with. Newly triggered runs use the new version.
Can I cancel a stuck run? Yes β open the run in the monitoring page and click cancel. The remaining actions are skipped.
Next steps β
- Monitoring runs β debug what happened.
- Newcomer follow-up workflow β full multi-step recipe.
- Actions β the full catalog.