Temporal ⇄ Pulse
Temporal owns durable orchestration; Pulse is the real-time streaming step it calls. Repo example: examples/temporal-pulse-bridge/.
Why an Activity — the one design constraint that matters
Temporal workflows are deterministic and replay-safe, so they can't do I/O directly — every external call lives in an Activity. Pulse is therefore a step inside an Activity, and Temporal wraps it with durable retries / timeouts / exactly-once semantics:
The Activity does the same two calls as every other bridge:
POST /api/pulse/x/order-scoring/in
GET /api/pulse/events/order-scoring.score.out
Run it
pulse server start --dev
mkdir app && cp pulse.yaml app/ && (cd app && pulse deploy .) # stands up order-scoring
pip install temporalio requests
python run.py
run.py boots a local Temporal dev server in-process (WorkflowEnvironment.start_local()), starts a worker hosting OrderWorkflow + the score_order Activity, and executes the workflow:
amount= 2500 -> high_value=True decision=escalate
amount= 300 -> high_value=False decision=auto-approve
What's validated — stated precisely
- The Activity's Pulse call is validated live against a
--devserver (same POST-ingress + read-topic contract as the n8n/LangGraph bridges). - The Temporal wiring is real —
@workflow.defn/@activity.defnontemporalio1.30. - The full in-process workflow run needs Temporal's dev server binary, which the repo's CI sandbox can't fetch — run
python run.pyon your machine to see the complete durable loop.
What each side contributes
| Concern | Owner |
|---|---|
| Durable state, retries, timeouts, human tasks | Temporal |
| Per-key windows, joins, dedup, LLM/MCP stages on the stream | Pulse |
| The seam | one Activity with two HTTP calls |
This is the cleanest division of labor of all the bridges: Temporal never sees the event firehose, Pulse never re-implements durable orchestration.
Next
- Crash-resume — Pulse's own durability story
- n8n guide · LangGraph guide