Skip to content

nc1z/temporal-demo

Repository files navigation

Temporal Workflow Demo 🚀

This repository demonstrates how Temporal can be used for distributed workflow orchestration in a modern TypeScript monorepo. It showcases how Temporal handles complex business processes across multiple services with built-in reliability.

Built With

Overview 📋

The demo implements an investment workflow that spans multiple services:

graph LR
    API[REST API] --> T[Temporal Server]
    T --> IW[Investment Worker]
    IW --> T
    T --> EW[Email Worker]
Loading
  • apps/api: REST API that initiates workflows
  • apps/investment-worker: Handles investment processing
  • apps/email-worker: Manages email notifications
  • Temporal Server: Orchestrates the entire workflow

Getting Started 🏃

  1. Install dependencies:
pnpm install
  1. Start Temporal Server:
pnpm temporal  # or pnpm temporal:start

# To stop the server later:
pnpm temporal:stop
  1. Start all services:
pnpm dev

This will start:

Try It Out ✨

Make an investment request:

# Start an investment workflow
curl -X POST http://localhost:3000/invest \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "amount": 1000
  }'

# Response:
# {
#   "workflowId": "investment-user123-1234567890"
# }

The workflow will:

  1. Record the investment (handled by investment-worker)
  2. Send a confirmation email (handled by email-worker)
  3. You can watch the progress in the logs or Temporal UI

Example: Workflow Resilience 💪

Here's a demonstration of Temporal's durability:

  1. Start a workflow as shown above
  2. Investment worker logs:
Investment workflow started { userId: 'user123', amount: 1000 }
Investment recorded { userId: 'user123' }
[Process exits unexpectedly]
  1. The workflow will pause. Start the services again:
pnpm dev
  1. Watch it continue automatically:
Worker connected, waiting for tasks...
Starting email workflow { userId: 'user123' }
Investment workflow completed { userId: 'user123' }

The workflow continues without any data loss or manual intervention! 🎉

Project Structure 📁

apps/
  ├── api/              # REST API
  ├── investment-worker # Investment processing service
  └── email-worker     # Email notification service
infra/
  └── temporal/        # Temporal server configuration

Sample Output 📝

When you run the workflow, you'll see the following logs:

Investment Worker

Worker connected, waiting for tasks...
2025-08-17T12:20:13.521Z [INFO] Worker state changed {
  sdkComponent: 'worker',
  taskQueue: 'investment-queue',
  state: 'RUNNING'
}
2025-08-17T12:20:31.037Z [INFO] Investment workflow started {
  sdkComponent: 'workflow',
  taskQueue: 'investment-queue',
  namespace: 'default',
  workflowId: 'investment-user2-1755433230984',
  runId: '0198b7f9-628b-7a13-999c-4bbd8e1b8366',
  workflowType: 'investmentWorkflow',
  userId: 'user2',
  amount: 500
}
Recording investment { userId: 'user2', amount: 500 }
Investment saved to memory { userId: 'user2' }
2025-08-17T12:20:31.069Z [INFO] Investment recorded {
  sdkComponent: 'workflow',
  taskQueue: 'investment-queue',
  namespace: 'default',
  workflowId: 'investment-user2-1755433230984',
  runId: '0198b7f9-628b-7a13-999c-4bbd8e1b8366',
  workflowType: 'investmentWorkflow',
  userId: 'user2',
  amount: 500
}
2025-08-17T12:20:31.081Z [INFO] Starting email workflow {
  sdkComponent: 'workflow',
  taskQueue: 'investment-queue',
  namespace: 'default',
  workflowId: 'investment-user2-1755433230984',
  runId: '0198b7f9-628b-7a13-999c-4bbd8e1b8366',
  workflowType: 'investmentWorkflow',
  userId: 'user2'
}
2025-08-17T12:20:31.096Z [INFO] Investment workflow completed {
  sdkComponent: 'workflow',
  taskQueue: 'investment-queue',
  namespace: 'default',
  workflowId: 'investment-user2-1755433230984',
  runId: '0198b7f9-628b-7a13-999c-4bbd8e1b8366',
  workflowType: 'investmentWorkflow',
  userId: 'user2'
}

Email Worker

2025-08-17T12:20:13.521Z [INFO] Worker state changed { sdkComponent: 'worker', taskQueue: 'email-queue', state: 'RUNNING' }
2025-08-17T12:20:31.133Z [INFO] Email workflow started {
  sdkComponent: 'workflow',
  taskQueue: 'email-queue',
  namespace: 'default',
  workflowId: 'email-user2-1755433231075',
  runId: '0198b7f9-62ed-7d55-8f07-0e34e14dc45a',
  workflowType: 'sendEmailWorkflow',
  to: 'user2@example.com'
}

=== Simulated Email ===
To: user2@example.com
Subject: Investment Confirmation
Body: Your investment of $500 has been received.
====================

Email sent successfully
2025-08-17T12:20:31.680Z [INFO] Email workflow completed {
  sdkComponent: 'workflow',
  taskQueue: 'email-queue',
  namespace: 'default',
  workflowId: 'email-user2-1755433231075',
  runId: '0198b7f9-62ed-7d55-8f07-0e34e14dc45a',
  workflowType: 'sendEmailWorkflow',
  to: 'user2@example.com'
}

These logs show the complete flow:

  1. Investment worker receives and processes the investment
  2. Triggers the email workflow
  3. Email worker receives and processes the email request
  4. Both workflows complete successfully

About

Spike showcasing the beauty of workflow orchestration with Temporal

Topics

Resources

Stars

Watchers

Forks

Contributors