Faster CI with a Rust-based cache layer
How I cut build times 60% by rewriting the cache layer that sat between CI and object storage.
Our CI spent more time downloading caches than building. The culprit was a Python shim doing synchronous, un-deduplicated uploads. I rewrote it in Rust over a weekend.
Content-addressed, concurrent
Every artifact is keyed by the hash of its inputs. If the hash exists, we skip the upload entirely — and we do the existence checks concurrently with tokio.
pub async fn store(items: Vec<Artifact>) -> Result<()> {
let tasks = items.into_iter().map(|a| async move {
if !exists(&a.key).await? {
upload(&a).await?;
}
Ok(())
});
try_join_all(tasks).await?;
Ok(())
} The result: a p50 cache step that went from 90s to 34s. The numbers that mattered weren’t CPU — they were the requests we didn’t make.