Checkpointing and Fault Tolerance in Distributed LLM Training: A Practical Guide

Checkpointing and Fault Tolerance in Distributed LLM Training: A Practical Guide

Imagine spending three weeks training a large language model on 10,000 GPUs, only to lose it all because one node crashed at hour 400. In the world of distributed LLM training, this isn't just a nightmare; it's a statistical certainty if you don't have robust checkpointing and mechanisms to save and restore training state automatically. As models grow from billions to trillions of parameters, the cost of failure skyrockets. You need more than just saving files every few hours. You need a strategy that balances I/O overhead with recovery speed, ensuring your cluster keeps churning through data even when hardware fails.

The Core Problem: Why Standard Checkpoints Fail at Scale

Traditional HPC (High-Performance Computing) checkpointing was designed for jobs running on clusters of hundreds of nodes. Modern LLM training runs on thousands or tens of thousands of accelerators. The fundamental issue is synchronization. In synchronous data parallelism, if one rank fails, the entire job stalls while waiting for that rank to catch up or restart. This creates a single point of failure that can suspend the whole process.

A standard checkpoint includes:

  • Model Parameters: The weights of the neural network.
  • Optimizer State: Momentum buffers (like Adam’s first and second moments) which are crucial for convergence stability.
  • Training Metadata: Global step count, epoch number, learning rate scheduler state.
  • RNG Seeds: To ensure bit-wise reproducibility of random operations.

At the scale of Google’s November 2023 Multislice Training run on 50,944 Cloud TPU v5e chips, losing even a few hours of progress means wasting thousands of GPU-hours. If your checkpoint interval is too long, you waste compute. If it’s too short, the I/O bottleneck slows down actual training. Finding that sweet spot is the core engineering challenge.

Sharded vs. Monolithic: How State is Saved

In distributed setups, you rarely save one giant file. Instead, the training state is partitioned across ranks. Each GPU or TPU writes its own shard of the model and optimizer state. This approach, known as Distributed Checkpointing or DCP, allows for parallel I/O. Rather than one disk being hammered by all processes, each node writes to its local storage simultaneously.

This sharding has significant implications for recovery. When a job restarts, the system must reassemble these shards correctly. If you lose a node, you don't just reload a file; you need to map the new set of healthy ranks to the existing shards. Frameworks like PyTorch’s Distributed Checkpointing handle this mapping logic, ensuring that a rank restarting on a different physical device can still load the correct portion of the state.

In-Cluster Checkpointing: Reducing Latency

Writing checkpoints to remote object stores like Amazon S3 or Google Cloud Storage introduces latency. For large models, this can take minutes or even hours. To solve this, teams at Google and Meta developed In-Cluster Checkpointing, built on PyTorch DCP APIs. The idea is simple but powerful: save checkpoints to node-local SSDs first.

Here’s how it works in practice:

  1. Local Write: Each node saves its state shard to its local high-speed SSD. This is fast and doesn't block the network.
  2. Async Replication: In the background, these local shards are replicated to durable remote storage or neighboring nodes.
  3. Recovery: If a node fails, the replacement node pulls the necessary shards from the local cluster storage rather than fetching them from a distant cloud bucket.

This approach has shown measurable results. Production deployments report up to a 5% increase in training goodput and a reduction in checkpoint-related badput (wasted compute) by over 50%. By keeping I/O local, you minimize the time the training loop spends waiting for disks.

DC comic style art showing data being written to local SSDs with cloud backup

Tiered Storage and TierCheck

Not all data needs the same level of durability immediately. This concept drives TierCheck, a tiered checkpointing architecture proposed in recent research. It utilizes multiple storage tiers:

  • Tier 1 (Hot): Node-local NVMe SSDs for frequent, low-latency saves.
  • Tier 2 (Warm): Rack-local shared storage for intermediate durability.
  • Tier 3 (Cold): Remote object stores for long-term archival.

By distributing checkpoint versions across these tiers, you reduce the aggregate I/O pressure on any single storage backend. For example, you might save a full checkpoint to local SSD every 10 steps, but only promote a compressed version to the cold tier every 100 steps. This allows for much higher checkpoint frequency without overwhelming the network, reducing the maximum amount of lost work upon failure.

Checkpointless Fault Tolerance: The torchft Approach

What if checkpointing is too slow? Enter torchft, a fault-tolerant implementation of Distributed Data Parallel (DDP) in PyTorch. Instead of relying on persistent disk checkpoints, torchft uses live replicas for recovery.

Workers are organized into replica groups. Gradients are synchronized within each group. If a group fails, it is restarted asynchronously. Crucially, the restarted workers don't load from disk. Instead, they perform an asynchronous peer-to-peer weight transfer from a healthy replica group. Since the transfer happens over the network between active GPUs, it is often faster than reading terabytes of data from disk.

In a demonstration training a LLaMA-like model on Crusoe L40S GPUs, researchers induced 2,000 synthetic failures every 15 seconds. With checkpointing disabled entirely, training continued seamlessly as long as at least one group remained healthy. This approach is ideal for environments with extremely high failure rates, where the overhead of constant disk writes would dominate the training time.

Comparison of Fault Tolerance Strategies
Strategy Mechanism Best For Overhead
Global Single-Tier All ranks write to shared NFS/S3 Small clusters, simple setups High I/O bottleneck, coarse recovery
In-Cluster (DCP) Node-local SSDs + async replication Large clusters, moderate failure rates Low latency, ~5% goodput gain
Tiered (TierCheck) Multi-tier storage hierarchy Very large models, cost optimization Complex management, reduced bandwidth use
Checkpointless (torchft) P2P weight transfer from healthy peers Extremely high failure rates No disk I/O, requires redundant groups
Comic style image of healthy workers transferring data to a failed peer

Integrating with Orchestration and Monitoring

Checkpointing doesn't exist in a vacuum. It must integrate with your orchestration layer, whether that's Kubernetes, Slurm, or Ray. The orchestrator detects node crashes and schedules new pods. Your training script must then automatically discover the latest valid checkpoint and resume from there.

Key integration points include:

  • Restart Policies: Configure Kubernetes or Slurm to restart failed jobs automatically.
  • Checkpoint Discovery: The entry point should scan the storage prefix for the highest step number before initializing the model.
  • Monitoring Metrics: Track checkpoint latency, failure counts, and restart attempts. If checkpoint time exceeds 10% of the training step time, you need to optimize your I/O path.

Companies like Together AI now hire specialized "Checkpoint Optimization Engineers" specifically to manage this integration, highlighting that this is a distinct discipline within ML infrastructure. The role involves tuning serialization formats, managing storage layouts, and ensuring that the data pipeline doesn't become a bottleneck during save/load operations.

Best Practices for Implementation

Based on industry case studies and production experience, here are practical guidelines for implementing robust fault tolerance:

  1. Start Local: Always prefer node-local storage for initial checkpoint writes. Use async threads to push data to remote storage later.
  2. Validate Integrity: Corrupted checkpoints are worse than no checkpoints. Implement checksums or validation steps during load to ensure state consistency.
  3. Automate Recovery: Never rely on manual intervention. Your scripts must handle the "resume from last checkpoint" logic automatically upon job start.
  4. Combine Strategies: Use frequent local checkpoints for safety and periodic remote backups for durability. Consider adding torchft-style redundancy if your cluster has unstable hardware.
  5. Monitor Badput: Measure the percentage of total compute time spent on checkpointing. Aim to keep this below 5-10%.

Frequently Asked Questions

How often should I save checkpoints in LLM training?

It depends on your failure rate and I/O speed. A common heuristic is to save every 10-30 minutes or every 1,000-5,000 steps. If your checkpoint write takes 5 minutes, saving every 10 minutes means you lose at most 15 minutes of work on average. With in-cluster storage, you can afford much shorter intervals, such as every 100 steps.

What is the difference between model weights and optimizer state in a checkpoint?

Model weights are the current parameters of the network. Optimizer state includes internal variables used by optimizers like Adam or SGD, such as momentum and variance estimates. Saving only weights will cause the optimizer to "forget" its history, potentially leading to unstable convergence or slower learning rates. For serious training, always save both.

Can I use checkpointless fault tolerance with any framework?

Currently, it is most mature in PyTorch via torchft. Other frameworks may require custom implementations of peer-to-peer state synchronization. The key requirement is that the framework supports asynchronous gradient synchronization and allows dynamic reconfiguration of worker groups without stopping the entire job.

Why is sharded checkpointing better than a single file?

A single file creates a centralized I/O bottleneck where all processes compete for the same storage bandwidth. Sharded checkpointing allows each rank to write independently to its local storage, utilizing parallel I/O paths. This reduces the total time required to complete a checkpoint and scales linearly with the number of nodes.

How do I handle data loader state after resuming from a checkpoint?

You should save the data loader's shuffle seed and the index of the last processed batch. Upon resuming, reconstruct the data loader with the saved seed and skip ahead to the correct position. This ensures that the model sees the exact same sequence of data as it did before the interruption, maintaining reproducibility.