Temporal: Workflow Orchestration
Master Temporal for durable execution, distributed workflows, and reliable business process automation
What is Temporal?
Temporal is a durable execution platform that enables developers to build scalable and reliable applications by providing guarantees around workflow execution. It handles failures, retries, timeouts, and state management automatically, allowing you to focus on business logic rather than distributed systems complexity.
Core Concepts
- • Workflows (orchestration logic)
- • Activities (external interactions)
- • Signals & Queries
- • Schedules & Timers
- • Workers & Task Queues
Key Guarantees
- • Durable execution
- • Automatic retries
- • Failure recovery
- • Exactly-once semantics
- • Infinite scalability
Core Features
Workflow Orchestration
Durable execution of long-running business processes with automatic state management
Use Case: Complex business workflows, saga patterns, multi-step processes with rollback
Implementation Example
// Workflow definition
@WorkflowInterface
public interface OrderProcessingWorkflow {
@WorkflowMethod
OrderResult processOrder(OrderRequest request);
}
// Workflow implementation
@WorkflowImplementation(OrderProcessingWorkflow.class)
public class OrderProcessingWorkflowImpl implements OrderProcessingWorkflow {
private final PaymentActivities paymentActivities =
Workflow.newActivityStub(PaymentActivities.class,
ActivityOptions.newBuilder()
.setScheduleToCloseTimeout(Duration.ofMinutes(5))
.setRetryOptions(RetryOptions.newBuilder()
.setMaximumAttempts(3)
.build())
.build());
private final InventoryActivities inventoryActivities =
Workflow.newActivityStub(InventoryActivities.class);
@Override
public OrderResult processOrder(OrderRequest request) {
// Step 1: Validate and reserve inventory
ReservationResult reservation = inventoryActivities.reserveItems(request.getItems());
// Step 2: Process payment with timeout and retry
PaymentResult payment = paymentActivities.processPayment(
request.getPaymentInfo(), reservation.getTotalAmount());
// Step 3: Fulfill order if payment successful
if (payment.isSuccessful()) {
FulfillmentResult fulfillment = inventoryActivities.fulfillOrder(reservation);
return OrderResult.success(fulfillment.getTrackingNumber());
} else {
// Compensate: Release reserved inventory
inventoryActivities.releaseReservation(reservation);
return OrderResult.failure(payment.getErrorMessage());
}
}
}
Key Benefits
Workflow Execution Monitor
Cluster Activity
Success Rate: 99%
Running
245
Completed
1,832
Failed
12
Retrying
8
Workflow Types
Implementation Patterns
Saga Pattern Implementation
Distributed transaction management with automatic compensation
Implementation: Long-running transactions across multiple services with rollback
Detailed Implementation
// Saga workflow for distributed transaction
@WorkflowImplementation(BookingWorkflow.class)
public class BookingWorkflowImpl implements BookingWorkflow {
private final FlightActivities flightActivities =
Workflow.newActivityStub(FlightActivities.class);
private final HotelActivities hotelActivities =
Workflow.newActivityStub(HotelActivities.class);
private final CarActivities carActivities =
Workflow.newActivityStub(CarActivities.class);
private final PaymentActivities paymentActivities =
Workflow.newActivityStub(PaymentActivities.class);
@Override
public BookingResult bookTrip(TripRequest request) {
List<CompensationAction> compensations = new ArrayList<>();
try {
// Step 1: Book flight
FlightBooking flight = flightActivities.bookFlight(
request.getFlightDetails());
compensations.add(() -> flightActivities.cancelFlight(flight.getId()));
// Step 2: Book hotel
HotelBooking hotel = hotelActivities.bookHotel(
request.getHotelDetails());
compensations.add(() -> hotelActivities.cancelHotel(hotel.getId()));
// Step 3: Book car rental
CarBooking car = carActivities.bookCar(request.getCarDetails());
compensations.add(() -> carActivities.cancelCar(car.getId()));
// Step 4: Process payment
PaymentResult payment = paymentActivities.processPayment(
calculateTotal(flight, hotel, car), request.getPaymentMethod());
if (payment.isSuccessful()) {
// Send confirmation
sendConfirmation(request.getCustomerEmail(), flight, hotel, car);
return BookingResult.success(generateItinerary(flight, hotel, car));
} else {
throw new PaymentFailedException("Payment failed: " + payment.getErrorMessage());
}
} catch (Exception e) {
// Execute compensations in reverse order
executeCompensations(compensations);
return BookingResult.failure(e.getMessage());
}
}
private void executeCompensations(List<CompensationAction> compensations) {
// Execute compensations in reverse order (LIFO)
for (int i = compensations.size() - 1; i >= 0; i--) {
try {
compensations.get(i).compensate();
} catch (Exception e) {
// Log compensation failure but continue
Workflow.getLogger(this.getClass()).error("Compensation failed", e);
}
}
}
private interface CompensationAction {
void compensate() throws Exception;
}
}
// Enhanced saga with parallel execution and timeouts
@WorkflowImplementation(ParallelSagaWorkflow.class)
public class ParallelSagaWorkflowImpl implements ParallelSagaWorkflow {
@Override
public OrderResult processOrder(OrderRequest request) {
// Execute some activities in parallel
Promise<InventoryResult> inventory = Async.function(
inventoryActivities::reserveItems, request.getItems());
Promise<CreditCheckResult> creditCheck = Async.function(
creditActivities::checkCredit, request.getCustomerId());
Promise<ShippingQuote> shipping = Async.function(
shippingActivities::getQuote, request.getShippingAddress());
// Wait for all with timeout
try {
Promise.allOf(inventory, creditCheck, shipping)
.get(Duration.ofMinutes(5));
} catch (Exception e) {
// Compensate any completed operations
if (inventory.isCompleted() && inventory.get().isSuccess()) {
inventoryActivities.releaseReservation(inventory.get().getReservationId());
}
throw new ApplicationFailure("Parallel operations failed", "TIMEOUT");
}
// Continue with sequential operations
if (creditCheck.get().isApproved()) {
PaymentResult payment = paymentActivities.processPayment(
request.getPayment(), calculateTotal(inventory.get(), shipping.get()));
if (payment.isSuccessful()) {
return fulfillOrder(inventory.get(), shipping.get());
} else {
inventoryActivities.releaseReservation(inventory.get().getReservationId());
throw new PaymentFailedException();
}
}
return OrderResult.rejected("Credit check failed");
}
}
Key Considerations
- →Compensation order (LIFO)
- →Idempotent compensations
- →Partial failure handling
- →Timeout management
- →State consistency
Temporal vs Alternatives
Feature | Temporal | AWS Step Functions | Apache Airflow | Cadence |
---|---|---|---|---|
Durable Execution | ✓ Native | ✓ Built-in | ○ Limited | ✓ Native |
Programming Model | Code-First | JSON/YAML | Code-First | Code-First |
Scalability | Very High | Very High | Medium | Very High |
Deployment | Self-hosted | Managed | Self-hosted | Self-hosted |
Real-time Signals | ✓ Built-in | ✗ Limited | ✗ No | ✓ Built-in |
Long-running Workflows | ✓ Years | ○ 1 Year | ✗ Days | ✓ Years |
Best Practices
Workflow Design
- •Keep workflows deterministic
- •Use activities for external calls
- •Design for idempotency
- •Handle versioning from day one
Performance
- •Use appropriate task queue configurations
- •Optimize activity retry policies
- •Use local activities for fast operations
- •Monitor worker resource usage
Reliability
- •Implement proper error handling
- •Use heartbeats for long activities
- •Test failure scenarios
- •Monitor workflow execution health
Operations
- •Use Temporal Web UI for monitoring
- •Implement comprehensive logging
- •Set up alerting on failed workflows
- •Plan for disaster recovery