Temporal is a durable execution platform — write workflows as code that survive crashes, network failures, and server restarts. Used by Netflix, Coinbase, and Stripe.
Why Temporal?
- Durable execution: Code resumes exactly where it stopped
- Any language: TypeScript, Go, Java, Python, PHP
- Scalable: Handles millions of concurrent workflows
- Retry policies: Automatic with custom backoff
- Visibility: Query workflow state anytime
- Open source: Self-host with full features
Self-Host
git clone https://github.com/temporalio/docker-compose.git
cd docker-compose
docker compose up -d
Web UI at http://localhost:8233
TypeScript Workflow
import { proxyActivities, sleep } from '@temporalio/workflow';
import type * as activities from './activities';
const { sendEmail, chargeCard, fulfillOrder } = proxyActivities<typeof activities>({
startToCloseTimeout: '30s',
retry: { maximumAttempts: 3 },
});
export async function orderWorkflow(order: Order): Promise<OrderResult> {
// Step 1: Charge the card
const charge = await chargeCard(order.paymentMethod, order.total);
// Step 2: Send confirmation email
await sendEmail(order.customerEmail, 'Order Confirmed', `Order #${order.id}`);
// Step 3: Wait 30 minutes, then fulfill
await sleep('30 minutes');
// Step 4: Fulfill the order
const fulfillment = await fulfillOrder(order.id, charge.id);
return { orderId: order.id, status: 'completed', trackingNumber: fulfillment.tracking };
}
If the server crashes during sleep('30 minutes'), Temporal resumes from exactly that point.
Activities
// activities.ts
export async function chargeCard(method: string, amount: number) {
const charge = await stripe.charges.create({ amount, source: method });
return { id: charge.id };
}
export async function sendEmail(to: string, subject: string, body: string) {
await emailService.send({ to, subject, body });
}
export async function fulfillOrder(orderId: string, chargeId: string) {
const result = await warehouse.ship(orderId);
return { tracking: result.trackingNumber };
}
Start a Workflow
import { Client } from '@temporalio/client';
const client = new Client();
const handle = await client.workflow.start(orderWorkflow, {
taskQueue: 'orders',
workflowId: `order-${orderId}`,
args: [{ id: orderId, total: 4999, customerEmail: 'user@example.com' }],
});
// Check status later
const result = await handle.result();
Query Workflow State
// In workflow
import { defineQuery } from '@temporalio/workflow';
export const getStatus = defineQuery<string>('getStatus');
let status = 'pending';
export async function orderWorkflow(order: Order) {
status = 'charging';
await chargeCard(order.paymentMethod, order.total);
status = 'fulfilling';
await fulfillOrder(order.id);
status = 'completed';
}
// Query from outside
const status = await handle.query(getStatus);
Cron Workflows
await client.workflow.start(dailyReport, {
taskQueue: 'reports',
workflowId: 'daily-report',
cronSchedule: '0 9 * * *',
});
Real-World Use Case
Coinbase uses Temporal for crypto transactions — each transfer is a workflow that handles signing, broadcasting, and confirmation. If a node goes down mid-transfer, Temporal picks up exactly where it left off. Zero lost transactions across millions of daily transfers.
Need to automate data collection? Check out my Apify actors for ready-made scrapers, or email spinov001@gmail.com for custom solutions.
Top comments (1)
Have you checked out DBOS? I think you'd like it. It's much easier to use and doesn't require an external coordinator -- it turns your program into it's own durable executor.