O sccache é o jeito mais direto de parar de recompilar as mesmas crates Rust em todo cargo build da CI e do time: ele envolve o rustc via RUSTC_WRAPPER=sccache e reutiliza resultados idênticos entre máquinas, branches e pipelines. Instale com cargo install sccache --locked, exporte o wrapper e valide com sccache --show-stats. Em monorepos e em empresas que usam Rust com dezenas de serviços, o impacto costuma ser maior do que qualquer micro-otimização de código.
Este guia cobre o que é o sccache, como instalá-lo, como configurá-lo localmente e na CI, como usar backends remotos (S3/GCS/Redis), como combiná-lo com mold, cargo-chef e cargo-nextest, e como evitar os erros que zeraram o cache de muita equipe em 2026. Se o seu problema ainda é “não sei onde o build gasta tempo”, comece pelo guia de tempo de compilação e só depois invista em backend remoto.
Por que cache de compilação importa em Rust
Rust paga um preço alto na compilação por razões boas: monomorfização de genéricos, otimizações agressivas, verificação estática profunda e crates com muitas features. Em um serviço Axum + Tokio + Serde + SQLx, o grafo de dependências facilmente passa de centenas de crates.
Sem cache compartilhado, cada cenário repete o mesmo trabalho:
- notebook do dev A compila
hyperetokiodo zero; - notebook do dev B repete a mesma compilação no dia seguinte;
- CI no PR recompila quase tudo a cada push;
- job de release recompila de novo com flags levemente diferentes.
O Cargo já tem target/ incremental local. Isso ajuda você no mesmo checkout. Não ajuda o colega, não ajuda o runner efêmero da CI e não ajuda outro repositório que depende das mesmas versões. O sccache preenche exatamente esse buraco: cache de compilador entre contextos.
O que é sccache
sccache (Shared Compilation Cache) é um wrapper de compilador mantido pela comunidade (origem Mozilla) que intercepta invocações de rustc, gcc, clang e outros. Para Rust, o fluxo prático é:
- o Cargo decide o que compilar;
- em vez de chamar
rustcdireto, o ambiente apontaRUSTC_WRAPPER=sccache; - o sccache calcula uma chave a partir das entradas relevantes (código, flags, toolchain, target, etc.);
- se a chave já existe no cache, devolve o artefato; senão, compila e grava o resultado.
Importante: sccache não substitui o Cargo, não baixa crates do crates.io e não resolve o link final do binário. Ele cacheia o trabalho caro do rustc sobre crates cujas entradas não mudaram.
sccache vs cache de target/ vs cargo-chef
| Camada | O que reutiliza | Escopo típico | Limite |
|---|---|---|---|
target/ incremental do Cargo | objetos e metadados do checkout | mesma máquina / mesmo job | some com runner limpo |
| sccache | resultados de compilação do rustc | devs + CI + projetos | sensível a flags e toolchain |
| cargo-chef | layer Docker de dependências | builds containerizados | não ajuda build nativo fora da imagem |
| mold / LLD | nada de cache; acelera o link | Linux (mold) / multiplataforma (LLD) | não evita recompilar crates |
Regra prática: se o relatório de cargo build --timings mostra muito tempo em crates de dependência, sccache é candidato forte. Se o tempo está no link, vá para o mold. Se o Docker recompila deps a cada mudança de código, use cargo-chef.
Como instalar o sccache
Via Cargo (mais comum em dev)
cargo install sccache --locked
sccache --version
Binário de release
Em CI, muitas equipes preferem baixar o binário pré-compilado da página de releases do sccache para não gastar minutos compilando o próprio cacheador. Em imagens Docker de build, o binário estático ou o pacote da distro costuma ser mais previsível do que cargo install dentro do job.
Verificação mínima
export RUSTC_WRAPPER=sccache
cargo clean -p seu_crate_app # opcional: force recompile de algo pequeno
cargo build
sccache --show-stats
Na primeira execução você verá sobretudo misses. Na segunda, com o mesmo código e as mesmas flags, os hits devem subir. Se os hits ficarem em zero, o problema quase nunca é “sccache não funciona” — é chave instável (veja a seção de troubleshooting).
Configuração local: o mínimo que funciona
Wrapper no shell
# ~/.bashrc ou ~/.zshrc
export RUSTC_WRAPPER=sccache
# opcional: tamanho do cache local (exemplos)
export SCCACHE_CACHE_SIZE="20G"
Wrapper só em um projeto
Evite poluir o ambiente global se o time ainda está experimentando:
# na sessão do projeto
export RUSTC_WRAPPER=sccache
cargo build
cargo test
Para desligar temporariamente (debug de bug estranho no rustc):
unset RUSTC_WRAPPER
# ou
export RUSTC_WRAPPER=
Onde o cache local mora
Por padrão o sccache grava em um diretório de cache do usuário (variável e SO-específico). Em notebooks com SSD pequeno, limite o tamanho com SCCACHE_CACHE_SIZE. Em monorepos grandes, 10–50 GB de cache local não é exagero se você alterna entre branches e workspaces.
Backends remotos: S3, GCS, Redis e empresa
Cache local acelera você. Backend remoto acelera o time e a CI.
Quando vale a pena
- vários repositórios Rust com overlap de dependências;
- frota de runners efêmeros (GitHub Actions, Gitea Actions, GitLab);
- monorepo com dezenas de crates e PRs paralelos;
- builds de múltiplos targets (
x86_64-unknown-linux-gnu,aarch64, WASM, etc.) com overlap parcial.
Esboço com S3-compatível
export RUSTC_WRAPPER=sccache
export SCCACHE_BUCKET="empresa-sccache-rust"
export SCCACHE_REGION="sa-east-1"
# credenciais via IAM role, OIDC ou variáveis padrão AWS
export SCCACHE_S3_KEY_PREFIX="rust/"
Use prefixos por toolchain ou por repositório se quiser isolar políticas de retenção. Em ambientes corporativos brasileiros, buckets em sa-east-1 (São Paulo) reduzem latência de hit em relação a regiões distantes — meça; às vezes a CPU do compile ainda domina a rede.
GCS e Redis
GCS segue o mesmo espírito (bucket + credencial de service account). Redis aparece em setups que já têm Redis interno de baixa latência e querem cache quente entre jobs do mesmo cluster. A regra de ouro não muda: o backend só ajuda se as chaves forem estáveis.
Segurança
Cache de compilação pode conter artefatos derivados de código proprietário. Trate o bucket como dado interno:
- acesso autenticado (nada de bucket público);
- criptografia em repouso;
- política de lifecycle (apagar objetos antigos);
- segregação por ambiente se compliance exigir.
Não coloque secrets de produção dentro do cache de build; secrets pertencem a um gerenciador de segredos, não a objetos de compilação.
sccache na CI (GitHub Actions / Gitea Actions)
O padrão que funciona na maioria dos pipelines Rust:
- instalar sccache (binário);
- exportar
RUSTC_WRAPPER=sccache; - restaurar cache local ou apontar backend remoto;
- rodar
cargo build/cargo nextest; - gravar estatísticas no log (
sccache --show-stats); - persistir o cache local se não houver backend remoto.
Exemplo conceitual (local cache + actions/cache)
env:
RUSTC_WRAPPER: sccache
SCCACHE_CACHE_SIZE: "5G"
steps:
- uses: actions/checkout@v4
- name: Install sccache
run: |
# baixe o binário da release ou use cargo install --locked
sccache --version
- name: Cache sccache
uses: actions/cache@v4
with:
path: ~/.cache/sccache
key: sccache-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
sccache-${{ runner.os }}-
- name: Build
run: cargo build --workspace --all-targets
- name: Stats
run: sccache --show-stats
Ajuste o path do cache ao diretório real do sccache no runner. O key com Cargo.lock é um bom ponto de partida; chaves demais (que mudam a cada commit) destroem a taxa de hit.
CI com backend S3
Se vários workflows e repositórios compartilham o mesmo bucket, o actions/cache local vira complementar, não principal. OIDC para assumir role na AWS evita access keys de longa duração nos secrets do repositório — padrão recomendado em 2026.
O que logar sempre
rustc --version/rustup show;sccache --version;sccache --show-statsno final;- tempo total do job (para correlacionar hit rate com minutos economizados).
Sem essas linhas, ninguém prova que o cache está ajudando — e cache “mágico” sem métrica morre no próximo corte de custo.
Docker: sccache + multi-stage + cargo-chef
Docker e sccache se complementam, não se substituem.
Papel de cada um
- cargo-chef: evita recompilar dependências quando só o seu código mudou, graças a layers estáveis;
- sccache: reutiliza compilação de crates entre builds diferentes, imagens diferentes e até repos diferentes, se o backend for compartilhado;
- mold: encurta o link dentro do builder Linux.
Padrão saudável
- stage
chef/plannercom cargo-chef (como no guia dedicado); - stage
buildercom toolchain Rust, mold e sccache; ENV RUSTC_WRAPPER=sccacheno builder;- backend remoto ou volume de cache montado no builder;
- stage final mínimo só com o binário (sem sccache, sem toolchain).
Evite copiar o cache do sccache para a imagem final de produção. Cache é ferramenta de build, não runtime.
Para o desenho completo de imagens enxutas, veja também Rust e Docker: builds otimizados para produção.
Combinando sccache com o resto do kit 2026
Times maduros de Rust não escolhem uma ferramenta de build — montam um sistema:
| Sintoma | Ferramenta | Guia |
|---|---|---|
| Crates recompilam em todo job/CI | sccache (este guia) | — |
| Link lento no Linux | mold | mold linker |
| Docker recompila deps a cada commit | cargo-chef | cargo-chef |
| Suíte de testes lenta | cargo-nextest | nextest |
| Não sei onde o tempo vai | cargo build --timings | tempo de compilação |
| Pipeline completo | cache + test + deploy | CI/CD Rust |
| CPU em produção, não no build | profiling | profiling |
Ordem de adoção recomendada para um time que ainda não tem nada disso:
- medir com
--timings; - sccache local no dev + cache na CI;
- mold no Linux;
- cargo-chef no Docker;
- nextest na suíte;
- backend remoto de sccache quando o hit rate local provar valor.
Estabilidade da chave: o que mata o hit rate
A maior parte das decepções com sccache vem de chaves instáveis. Cada diferença abaixo pode transformar um hit em miss:
Toolchain diferente
rustc 1.8x.0 e 1.8x.1 não compartilham artefatos. Pine a toolchain com rust-toolchain.toml no repositório e use a mesma no CI.
RUSTFLAGS e profiles
Flags de link, cfg, -C target-cpu, sanitizers e profiles customizados entram na identidade da compilação. Um job de CI com RUSTFLAGS="-C debuginfo=0" e outro sem isso fragmenta o cache.
Features de workspace
Compilar cargo build -p api --features otel e cargo build -p api sem features gera artefatos diferentes para a mesma crate raiz e, em cascata, para dependências condicionais. Padronize features de CI.
Targets cruzados
x86_64-unknown-linux-gnu e aarch64-unknown-linux-gnu são caches distintos — e devem ser. Não espere que build amd64 aqueça o cache de arm64.
Paths absolutos e reproducibilidade
Alguns cenários sensíveis a path ainda aparecem em crates com build scripts antigos. Prefira builds determinísticos, Cargo.lock commitado e evite injetar timestamps em build.rs sem necessidade.
Troubleshooting rápido
sccache --show-stats sempre em zero hits
- confirme
echo $RUSTC_WRAPPER→ deve sersccache; - rode o mesmo
cargo buildduas vezes semcargo clean; - verifique se algum script faz
unset RUSTC_WRAPPER; - confira se a CI restaura o diretório/backend certo;
- veja se a toolchain muda entre runs.
Build fica mais lento com sccache
Pode acontecer no primeiro aquecimento ou com backend remoto de alta latência e hit rate baixo. Meça cold vs warm. Se o warm não ganhar, o gargalo não é recompilação de crates — olhe link e testes.
Erros estranhos só com o wrapper
Isole:
unset RUSTC_WRAPPER
cargo build
Se passar sem sccache, atualize o sccache, limpe o cache corrompido e abra issue com versões de rustc e sccache. Em paralelo, pin a versão do sccache na CI para não surfar breaking change no meio do sprint.
Cache estoura disco
Reduza SCCACHE_CACHE_SIZE, configure lifecycle no bucket ou separe prefixos por projeto. Cache sem política de retenção vira custo silencioso.
sccache e carreira: o que entrevistadores querem ouvir
Em vagas de backend sênior, plataforma e DevOps com Rust no Brasil, “como você reduz o tempo de feedback do monorepo?” virou pergunta clássica. Uma resposta forte não é “a gente usa sccache” — é:
- medimos com
cargo build --timingse métricas de CI; - separamos gargalos de compile, link e teste;
- aplicamos sccache / mold / chef / nextest onde cada um paga;
- acompanhamos hit rate e minutos de runner;
- documentamos toolchain e flags para o cache não apodrecer.
Isso demonstra engenharia de entrega, não só sintaxe de ownership. Para mapear o mercado, acompanhe vagas Rust, salários e o panorama de carreira em Rust.
Checklist de adoção
-
sccache --versionno PATH de dev e CI; -
RUSTC_WRAPPER=sccachedocumentado no README do time; -
rust-toolchain.tomlpinando a versão do compilador; - segundo
cargo buildlocal mostra hits em--show-stats; - CI imprime stats no fim do job;
- cache local persistido ou backend remoto configurado;
-
RUSTFLAGS/features padronizados entre jobs comparáveis; - mold habilitado no Linux se o link for gargalo;
- Docker multi-stage não leva sccache para a imagem final;
- política de retenção do cache (disco ou bucket) definida.
Conclusão
O sccache é a peça de cache de compilação que falta em muitos times Rust que já otimizaram código e ainda sangram minutos de CI. Ele não é mágica: exige toolchain estável, flags coerentes e métricas. Mas, quando a chave está correta, transforma o custo de recompilar tokio, hyper, serde e centenas de crates transitivas em hits baratos — no notebook, no PR e no release.
Monte o sistema completo: meça com timings, cacheie compile com sccache, acelere link com mold, estabilize Docker com cargo-chef e paralelize testes com nextest. Esse combo é o padrão de engenharia que aparece em times sérios de Rust em 2026 — e é o tipo de prática que o mercado brasileiro passa a cobrar quando a linguagem sai do piloto e entra no núcleo do produto.
Perguntas frequentes
O que é sccache?
sccache é um cache compartilhado de compilador. Em Rust, ele atua como RUSTC_WRAPPER, reutilizando resultados do rustc quando as entradas da compilação são as mesmas entre máquinas, branches e pipelines.
Como ativar sccache no Cargo?
cargo install sccache --locked
export RUSTC_WRAPPER=sccache
cargo build
sccache --show-stats
Na CI, instale o binário, exporte o wrapper e persista o cache local ou use backend remoto.
sccache substitui mold e cargo-chef?
Não. sccache cacheia compilação; mold acelera o link; cargo-chef estabiliza dependências em layers Docker. Combine conforme o gargalo medido.
sccache funciona com workspaces?
Sim. Workspaces com dependências compartilhadas são exatamente o cenário em que o hit rate costuma ser alto — desde que toolchain e features sejam estáveis.
sccache ou ccache?
Para Rust, prefira sccache. ccache é o clássico de C/C++; sccache entende o fluxo do rustc e é o padrão do ecossistema Rust em CI moderna.
Quando sccache não ajuda?
Quando o tempo está no link ou nos testes, quando cada job usa flags diferentes, ou quando a toolchain muda o tempo todo. Meça antes de escalar para S3.
Leia também
- Como reduzir o tempo de compilação do Rust
- mold linker: compilação mais rápida no Linux
- cargo-chef: cache de builds Docker em Rust
- cargo-nextest: testes Rust mais rápidos
- Rust e Docker: builds otimizados para produção
- CI/CD para projetos Rust
- Cargo: ferramentas essenciais
- Cargo no ecossistema Rust
- Profiling de performance em produção