A live, interactive demo showing why Temporal matters for order management. Place a taco order through an iPhone-style app, watch the behind-the-scenes workflow execute in real time, and see what happens when things go wrong.
Toggle between Traditional mode (direct service calls, no recovery) and Temporal mode (durable workflows with retries, signals, and compensation) — same failure, wildly different outcomes.
Prerequisites: Temporal CLI + either Docker or the language-specific toolchain for local mode.
./scripts/start.sh # Python worker (default)
./scripts/start.sh go # Go worker
./scripts/start.sh typescript # TypeScript worker
./scripts/start.sh java # Java worker
./scripts/start.sh dotnet # .NET (C#) workerThe script auto-detects your environment:
| Has Docker? | What happens |
|---|---|
| Yes | Temporal CLI on host, backend/worker/frontend in containers |
| No | Everything runs locally as background processes |
Open http://localhost:5173 once it's running. Temporal UI at http://localhost:8233.
Browse the menu, add items, and check out. The behind-the-scenes panel shows each workflow activity executing. The code panel on the right shows the actual workflow code — in the language of the running worker — lighting up in real time.
With the default "Store Connectivity" failure scenario, the store loses connection after payment is authorized. Switch to the Kitchen Display tab to see what happened:
Click "Plug It Back In" — the Temporal workflow's retry policy picks up the recovery automatically. The order appears on the KDS, and you can mark it ready:
Switch to Traditional mode in settings (gear icon) and place the same order. When the store goes down, the order fails — payment is taken but no food is coming. No retries, no compensation, no recovery.
Use the arrow keys to step through the "Evolution of Simple Architecture" diagram, showing the Rube Goldberg machine of queues, retry services, dead letter queues, state databases, and cron jobs that you'd need to build for reliability without Temporal.
The Temporal UI at http://localhost:8233 shows actual workflow executions with full event history:
Click the gear icon to configure:
- Architecture Mode: Traditional (fragile) vs Temporal (durable)
- Failure Scenario: Store connectivity (default), payment error, random chaos, or none
- Presentation Mode: Simple (high-level) vs Detailed (retries, payloads, error messages)
- Worker Language: Python, Go, TypeScript, Java, C# (the code view updates to match)
Browser (React + Vite + nginx)
↓ REST + SSE
FastAPI Backend (Python)
├── Mock Services (payment, store, cart)
├── Internal API (failure state, SSE events, store orders)
└── Temporal client (starts workflows, sends signals)
↕
Temporal Dev Server (CLI, on host)
↕
Worker (Python, Go, TypeScript, Java, or .NET — swappable)
├── OrderWorkflow (saga compensation, signals, queries)
└── Activities → Backend internal API
The worker runs as a separate process from the backend. Activities call the backend's internal API for failure state and store order registration, so the worker can be killed and restarted without losing sync — demonstrating Temporal's durable execution.
The same workflow is implemented in five languages. The backend is decoupled from the worker — it starts workflows and sends signals by string name, so any language's worker can be swapped in.
| Language | Run with | Saga Pattern |
|---|---|---|
| Python | ./scripts/start.sh python |
Manual compensation list + asyncio.shield |
| Go | ./scripts/start.sh go |
Compensations struct + NewDisconnectedContext |
| TypeScript | ./scripts/start.sh typescript |
Manual compensation list + CancellationScope.nonCancellable() |
| Java | ./scripts/start.sh java |
SDK's built-in Saga class (first-class support) |
| .NET (C#) | ./scripts/start.sh dotnet |
Manual compensation list with try/catch |
All workers implement the same flow: validate → authorize payment → clear cart → submit to store → wait for ready signal → capture payment. Same task queue (dejavu-tacos), same signal names, same compensation behavior.
The code view in the UI auto-detects the active worker language. To add a new language, see Adding a New Language.
├── frontend/ # React + Vite + TypeScript + Tailwind
│ └── src/data/ # Language-specific code definitions for the code viewer
├── backend/ # FastAPI + mock services (always Python)
├── workflows/
│ ├── python/ # Python worker — temporalio SDK
│ ├── go/ # Go worker — go.temporal.io/sdk
│ ├── typescript/ # TypeScript worker — @temporalio/* packages
│ ├── java/ # Java worker — io.temporal:temporal-sdk
│ └── dotnet/ # .NET worker — Temporalio NuGet package
├── docker/ # Dockerfiles + nginx config
├── docker-compose.yml # Container orchestration (one profile per language)
└── scripts/start.sh # One-command launcher
# Start with a specific worker language
DEJAVU_WORKER_LANGUAGE=go docker compose --profile go up --build
# Or use the launch script (handles Temporal dev server too)
./scripts/start.sh typescriptDocker Compose profiles: python, go, typescript, java, dotnet. Only the selected worker starts.
The launch script falls back to local mode if Docker isn't available:
./scripts/start.sh python # needs: uv, npm, temporal
./scripts/start.sh go # needs: go, npm, temporal
./scripts/start.sh typescript # needs: node/npm, temporal
./scripts/start.sh java # needs: gradle, jdk 17+, npm, temporal
./scripts/start.sh dotnet # needs: dotnet 8+, npm, temporal# Install dependencies
uv sync && cd frontend && npm install
# Run individual services
temporal server start-dev # Temporal on :7233
uv run --package dejavu-tacos-backend server # FastAPI on :8000
DEJAVU_BACKEND_URL=http://localhost:8000 uv run --package dejavu-workflows worker # Python worker
cd workflows/go && DEJAVU_BACKEND_URL=http://localhost:8000 go run ./cmd/worker/ # Go worker
cd workflows/typescript && npm run build && DEJAVU_BACKEND_URL=http://localhost:8000 node lib/worker.js
cd workflows/java && DEJAVU_BACKEND_URL=http://localhost:8000 gradle run
cd workflows/dotnet && DEJAVU_BACKEND_URL=http://localhost:8000 dotnet run
cd frontend && npm run dev # Vite on :5173- Validate Order — check items and prices
- Validate Store — confirm store is open
- Authorize Payment — place a hold (not a capture)
- Clear Cart — commit the order
- Submit to Store — send to kitchen (retries on failure)
- Await Order Ready — signal from KDS (human in the loop)
- Capture Payment — charge only after store confirms
Compensation (saga pattern): If store submission fails permanently, the workflow automatically releases the payment hold and notifies the customer. No manual intervention needed.
- Implement the workflow in
workflows/<lang>/— same activity event names, same task queue - Add code definition in
frontend/src/data/workflowCode.ts(code lines, compensation lines, syntax highlighting) - Add a Dockerfile in
docker/worker-<lang>.Dockerfile - Add a profile in
docker-compose.yml - Add a case in
scripts/start.sh - Add to
WorkerLanguagetype infrontend/src/types/index.ts






