Temporal: Workflow Orchestration

Master Temporal for durable execution, distributed workflows, and reliable business process automation

28 min readAdvanced
Not Started
Loading...

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

Automatic state persistence
Built-in retry mechanisms
Failure recovery
Versioning support
Distributed execution

Workflow Execution Monitor

Cluster Activity

Success Rate: 99%

Running

245

▶️

Completed

1,832

Failed

12

Retrying

8

🔄

Workflow Types

📋Order Processing
💳Payment Flows
📊Data Pipelines
👤Approval Flows

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

FeatureTemporalAWS Step FunctionsApache AirflowCadence
Durable Execution✓ Native✓ Built-in○ Limited✓ Native
Programming ModelCode-FirstJSON/YAMLCode-FirstCode-First
ScalabilityVery HighVery HighMediumVery High
DeploymentSelf-hostedManagedSelf-hostedSelf-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

📝 Test Your Knowledge

📝 Temporal Knowledge Quiz

1 of 5Current: 0/5

What is the main benefit of Temporal's durable execution?