2026-03-05 · 4 min read

Base Checkpoint Management in a Registry

Adapters are ephemeral; base models are long-lived. A registry must manage the relationship carefully so that an adapter trained on Qwen-v1.0 still works when Qwen-v2.0 is released.

The versioning problem

User downloads adapter sdxl-watercolor-lora-1.4.0 trained on stabilityai/stable-diffusion-xl-base-1.0 at revision abc123.

Six months later, Stability AI releases a patched version with a bug fix (revision xyz789). The revision hashes differ.

Does the adapter still work? Maybe. Maybe not. The mismatch is silent.

Solution: pin the exact revision in adapter metadata.

Metadata with revision pinning

{
  "slug": "sdxl-watercolor-lora",
  "version": "1.4.0",
  "base_model": "stabilityai/stable-diffusion-xl-base-1.0",
  "base_model_revision": "abc123def456789abcdef",
  "base_model_sha256": "sha256_of_model_weights",
  "created_at": "2025-07-01T10:00:00Z",
  "compatibility": [
    {
      "base_model": "stabilityai/stable-diffusion-xl-base-1.0",
      "revision": "abc123def456789abcdef",
      "tested": true
    }
  ]
}

The base_model_revision is non-negotiable. It's what prevents silent breakage.

Storing base model copies

Option 1: Let HuggingFace host (linked). - Pro: No storage cost - Con: Depends on external service; if they remove the model, your adapter is orphaned

Option 2: Mirror base models in your registry. - Pro: Independent; guaranteed availability - Con: Storage cost (7B model = 14 GB × 5 versions = 70 GB per base)

Hybrid: hot base models stored locally, cold ones on S3:

Hot (used by >10 adapters):
- stabilityai/stable-diffusion-xl-base-1.0
- Qwen/Qwen2.5-7B-Instruct
→ Local storage (fast downloads)

Cold (used by <3 adapters):
- llama3-8b-changelog-writer base
- flux-linework-lora base
→ S3 (cheap, slower fetch)

Migration workflow

When a base model is updated (Qwen2.5-7B-Instruct v1 → v2):

  1. Index affected adapters: sql SELECT * FROM adapters WHERE base_model = "Qwen/Qwen2.5-7B-Instruct" -- Result: 5 adapters depend on this base

  2. Test compatibility: bash for adapter in $(list_adapters_on_base "Qwen/Qwen2.5-7B-Instruct"); do python test_compatibility.py --adapter $adapter --base-revision new_hash done

  3. Document findings: json { "base_model_update": { "model": "Qwen/Qwen2.5-7B-Instruct", "from_revision": "old_hash", "to_revision": "new_hash", "tested_adapters": [ { "adapter": "qwen25-7b-support-tone", "status": "compatible", "regression": 0.0 }, { "adapter": "mistral-7b-json-extract", "status": "compatible", "regression": 0.005 } ], "action": "advisory: upgrade optional" } }

  4. Release advisory:

  5. If regression > 2% for any adapter: "Breaking change; adapters may need retraining"
  6. If regression < 1% for all: "Compatible; upgrade recommended"

  7. Update adapter metadata (optional, if new base is better): json { "compatibility": [ { "revision": "old_hash", "status": "deprecated" }, { "revision": "new_hash", "status": "current" } ] }

Health checks

Periodically verify that adapters still load:

def health_check_adapter(adapter_slug, base_model_id, base_revision):
    """Can this adapter load on the base model?"""
    try:
        base = AutoModelForCausalLM.from_pretrained(
            base_model_id,
            revision=base_revision
        )
        adapter = PeftModel.from_pretrained(base, adapter_slug)
        # Quick sanity: generate 5 tokens
        test_input = tokenizer("Test", return_tensors="pt")
        _ = adapter.generate(**test_input, max_length=10)
        return True, "OK"
    except Exception as e:
        return False, str(e)

# Run weekly on all adapters
for adapter in registry.list_adapters():
    ok, msg = health_check_adapter(adapter.slug, adapter.base_model, adapter.base_revision)
    if not ok:
        alert(f"Health check failed: {adapter.slug} - {msg}")

Lifecycle

Mark base model versions with status:

proposed → active → deprecated → archived → deleted

Example timeline for Qwen2.5-7B-Instruct:

2025-01-10  v1.0 released → active
2025-06-15  v2.0 released → proposed (test period)
2025-07-01  v2.0 → active; v1.0 → deprecated
2025-10-01  v1.0 → archived (still downloadable, no longer recommended)
2026-01-01  v1.0 deleted (rarely used; storage freed)

Communicating to users

When base model is deprecated, notify:

┌─ Adapter: qwen25-7b-support-tone v1.2.0
│
├─ ⚠️ Base model Qwen/Qwen2.5-7B-Instruct v1.0 is deprecated
├─    Consider upgrading to v2.0 (compatible, slight improvement)
│
├─ How to migrate:
│    mfl pull qwen25-7b-support-tone --base-version v2.0
│    (Retrains adapter on new base if needed)
│
└─ Deadline: 2025-10-01 (v1.0 will no longer be available)

Users have time to migrate; no surprise breakage.

Storage math

For a registry with 5 base models × 3 versions each:

Model       Versions  Size/version  Total
--------    --------  -----------   -----
SDXL        3         6 GB          18 GB
Qwen2.5-7B  3         14 GB         42 GB
Llama3-8B   3         16 GB         48 GB
FLUX.1-dev  3         24 GB         72 GB
Phi3-mini   3         4 GB          12 GB
--------                            ----
Total:                             192 GB

At $0.023/GB/month (S3 standard): - Hot storage (local SSD, maybe 100 GB): $0 - Cold storage (S3, 92 GB): $2.10/month

Negligible cost to maintain version history.

Immutable downloads

Link adapters to specific base model versions:

/download/qwen25-7b-support-tone-1.2.0?base-revision=abc123
/download/qwen25-7b-support-tone-1.2.0?base-revision=xyz789 (if compatible)

Users can explicitly choose which base version to download the adapter for. Reproducibility guaranteed.

Base checkpoint management is not exciting, but it's what separates a "registry that works for 6 months" from a "registry that works for 5 years."