Skip to content

Early Termination

Stop execution immediately when errors occur.

When NOT to Use Fail-Fast

Don't use fail-fast when you need results from all operations even if some fail (e.g., comprehensive test suites, migration validation). Use fail-fast when fast feedback matters more than complete results.


Shell Strict Mode

#!/bin/bash
set -euo pipefail

# set -e: Exit on first error
# set -u: Error on undefined variables
# set -o pipefail: Fail if any command in pipeline fails

deploy() {
    # Will exit immediately if any command fails
    kubectl apply -f deployment.yaml
    kubectl rollout status deployment/app
    kubectl get pods
}

deploy

GitHub Actions Matrix Fail-Fast

jobs:
  test:
    strategy:
      fail-fast: true  # Stop all jobs on first failure
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        node: [18, 20, 22]
    runs-on: ${{ matrix.os }}
    steps:
      - run: npm test

Use when: Fast feedback matters more than complete results.

Don't use when: You need results from all matrix combinations even if some fail.


Go Error Propagation

func processData() error {
    // Propagate errors immediately, don't swallow
    data, err := fetchData()
    if err != nil {
        return fmt.Errorf("fetch failed: %w", err)
    }

    transformed, err := transform(data)
    if err != nil {
        return fmt.Errorf("transform failed: %w", err)
    }

    if err := save(transformed); err != nil {
        return fmt.Errorf("save failed: %w", err)
    }

    return nil
}

// Bad: swallows errors
func processDataBad() error {
    data, _ := fetchData()  // Ignores error
    transformed, _ := transform(data)
    save(transformed)
    return nil
}

Circuit Breakers

type CircuitBreaker struct {
    failures   int
    threshold  int
    state      string // "closed", "open", "half-open"
}

func (cb *CircuitBreaker) Call(fn func() error) error {
    if cb.state == "open" {
        return fmt.Errorf("circuit breaker open, failing fast")
    }

    if err := fn(); err != nil {
        cb.failures++
        if cb.failures >= cb.threshold {
            cb.state = "open"
            return fmt.Errorf("circuit breaker tripped after %d failures: %w",
                cb.threshold, err)
        }
        return err
    }

    cb.failures = 0
    cb.state = "closed"
    return nil
}

Back to Fail Fast

Comments