# How uv-cache Implements Timestamp-Based Freshness Checking

> Discover how uv-cache uses CacheInfo and SystemTime to implement timestamp-based freshness checking, ensuring your cached artifacts are always up-to-date.

- Repository: [Astral/uv](https://github.com/astral-sh/uv)
- Tags: internals
- Published: 2026-03-01

---

**uv uses a `CacheInfo` metadata structure to store creation timestamps as `SystemTime` wrappers, comparing them against user-provided reference timestamps to determine if cached artifacts are fresh or stale.**

The `uv` package manager from Astral implements a robust timestamp-based freshness checking mechanism to avoid stale cache hits. This system relies on a small metadata structure called `CacheInfo` defined in the `uv-cache-info` crate, which records when a cached artifact was created and compares it against reference timestamps supplied via CLI flags like `--exclude-newer` or `--refresh`.

## Core Components of Timestamp-Based Freshness Checking

### CacheInfo Metadata Structure

The `CacheInfo` struct, defined in [`crates/uv-cache-info/src/cache_info.rs`](https://github.com/astral-sh/uv/blob/main/crates/uv-cache-info/src/cache_info.rs), serves as the primary container for cache metadata. It holds an optional `Timestamp` field that records when the cache entry was created:

```rust
pub struct CacheInfo {
    timestamp: Option<Timestamp>,
    // ... other fields
}

```

The struct provides the critical `is_fresh` method that performs the actual comparison:

```rust
pub fn is_fresh(&self, reference: &Timestamp) -> bool {
    self.timestamp.map_or(false, |ts| ts >= *reference)
}

```

This method returns `true` only if the cached timestamp is greater than or equal to the reference timestamp, ensuring that only entries created at or after the reference time are considered fresh.

### Timestamp Wrapper Type

The `Timestamp` type, implemented in [`crates/uv-cache-info/src/timestamp.rs`](https://github.com/astral-sh/uv/blob/main/crates/uv-cache-info/src/timestamp.rs), provides a thin, safe wrapper around `std::time::SystemTime`. It exposes several key methods used throughout the freshness checking pipeline:

- `Timestamp::now()` – Creates a timestamp representing the current system time when a new cache entry is created.
- `Timestamp::from_rfc3339(&str)` – Parses RFC 3339 formatted strings (used by the `--exclude-newer` CLI argument).
- `timestamp_millis()` – Returns the timestamp as milliseconds since the Unix epoch, used for comparisons in the resolver.

## How Freshness Checks Work in Practice

### Cache Entry Creation and Storage

When `uv` downloads a wheel, source distribution, or builds a distribution, it writes a cache-info JSON file alongside the artifact. For example, when caching a wheel with hash `<hash>`, `uv` creates `wheel-<hash>.json` containing:

```json
{
  "timestamp": "2024-05-15T10:30:00Z"
}

```

The `CacheInfo::from_path` method reads this JSON file to reconstruct the metadata when the cache entry is later accessed:

```rust
let cache_info = CacheInfo::from_path(&artifact_path)?;

```

### The Freshness Comparison Logic

During resolution or installation, `uv` loads the `CacheInfo` for each candidate distribution and compares its timestamp against a reference timestamp. The logic follows this pattern:

```rust
if let Some(cache) = cache_info {
    if cache.is_fresh(&exclude_newer) {
        // Use cached artifact
    } else {
        // Re-download or rebuild
    }
}

```

The `is_fresh` implementation ensures that if the cached timestamp is older than the reference (i.e., `ts < reference`), the entry is treated as stale and ignored.

### User-Controlled Reference Timestamps

Users control the reference timestamp through two primary mechanisms defined in [`crates/uv/src/settings.rs`](https://github.com/astral-sh/uv/blob/main/crates/uv/src/settings.rs):

1. **`--exclude-newer <RFC3339>`** – Parses the provided RFC 3339 timestamp into a `Timestamp` instance that serves as the upper bound for freshness. Any cache entry created after this date is excluded.

2. **`--refresh`** – Creates a virtual timestamp of "now" but instructs the resolver to **ignore** any existing `CacheInfo`, effectively treating all cache entries as stale regardless of their timestamp.

## Integration with the Resolver and Distribution System

### Version Map and Exclude-Newer Logic

The resolver integrates timestamp checking in [`crates/uv-resolver/src/version_map.rs`](https://github.com/astral-sh/uv/blob/main/crates/uv-resolver/src/version_map.rs). When evaluating available wheels for a package, the resolver checks each wheel's upload time against the `exclude_newer` threshold:

```rust
if upload_time >= exclude_newer.timestamp_millis() {
    // Exclude this wheel from consideration
}

```

This ensures that packages uploaded after the user-specified cutoff are not selected, even if they exist in the cache or index.

### Distribution Database Persistence

The `DistributionDatabase` in [`crates/uv-distribution/src/distribution_database.rs`](https://github.com/astral-sh/uv/blob/main/crates/uv-distribution/src/distribution_database.rs) handles the physical storage and retrieval of `CacheInfo` alongside distribution files. It ensures that:

- `CacheInfo` is written to disk immediately after a successful download or build.
- Metadata is read from disk and validated before reuse.
- Stale entries are purged and replaced with fresh downloads when the freshness check fails.

## Code Example: Checking Cache Freshness

The following Rust example demonstrates how `uv` determines whether a cached wheel can be reused:

```rust
use uv_cache_info::{CacheInfo, Timestamp};
use std::path::Path;

/// Determine whether a cached wheel can be reused.
fn wheel_is_fresh(wheel_path: &Path, exclude_newer: &Timestamp) -> anyhow::Result<bool> {
    // Load cache metadata stored next to the wheel.
    let cache = CacheInfo::from_path(wheel_path)?;
    
    // `is_fresh` returns true if the wheel's timestamp ≥ the user-provided timestamp.
    Ok(cache.is_fresh(exclude_newer))
}

```

When running the command:

```bash
uv pip install mypkg --exclude-newer 2024-05-01T00:00:00Z

```

`uv` creates a `Timestamp` from `2024-05-01T00:00:00Z` and applies the logic above to every cached distribution. Wheels created before this date are considered fresh and reused; those created after are re-downloaded.

## Summary

- **`CacheInfo`** stores optional timestamps in JSON files alongside cached artifacts, tracking when each entry was created.
- **`Timestamp`** wraps `SystemTime` to provide RFC 3339 parsing and millisecond comparisons used in freshness checks.
- **`is_fresh`** compares the cached timestamp against a reference timestamp, returning `true` only when the cache entry is newer than or equal to the reference.
- **CLI integration** allows users to specify reference timestamps via `--exclude-newer` or force invalidation with `--refresh`.
- **Resolver integration** applies these checks during package resolution in [`version_map.rs`](https://github.com/astral-sh/uv/blob/main/version_map.rs) and distribution retrieval in [`distribution_database.rs`](https://github.com/astral-sh/uv/blob/main/distribution_database.rs).

## Frequently Asked Questions

### What happens when a cache entry is considered stale?

When `CacheInfo::is_fresh` returns `false`, `uv` treats the cached artifact as invalid. The resolver ignores the stale entry and proceeds to download or build a fresh version from the package index. The old cache files are typically overwritten or removed during this process, ensuring that subsequent operations use the newly fetched artifact with updated metadata.

### How does the --exclude-newer flag interact with cache freshness?

The `--exclude-newer` flag accepts an RFC 3339 timestamp that `uv` parses into a `Timestamp` instance using `Timestamp::from_rfc3339`. This value serves as the reference timestamp passed to `CacheInfo::is_fresh`. During resolution, `uv` excludes any package versions with an `upload_time` greater than or equal to this threshold, effectively treating newer cached entries as stale and preventing their use.

### What is the difference between the Refresh flag and timestamp-based freshness?

The `--refresh` flag operates independently of timestamp comparisons. When enabled, it sets a `Refresh` flag in the settings that instructs the resolver to **ignore** all existing `CacheInfo` metadata, effectively treating every cache entry as stale regardless of its timestamp. In contrast, timestamp-based freshness checking uses `CacheInfo::is_fresh` to selectively invalidate entries based on their creation time relative to a reference timestamp, allowing older valid entries to be reused.

### Where is the CacheInfo JSON stored on disk?

`CacheInfo` metadata is persisted in JSON files stored alongside the cached artifacts in `uv`'s cache directory. When `uv` downloads a wheel or builds a distribution, it writes a JSON file (e.g., `wheel-<hash>.json`) containing the `timestamp` field to the same directory as the artifact. The `DistributionDatabase` in [`crates/uv-distribution/src/distribution_database.rs`](https://github.com/astral-sh/uv/blob/main/crates/uv-distribution/src/distribution_database.rs) handles these read and write operations, while `CacheInfo::from_path` reconstructs the metadata from these JSON files during cache lookups.