"Il CI è troppo lento" è la lamentela più frequente nei team in crescita. Sui nostri progetti abbiamo ridotto pipeline da 14 minuti a 3 applicando questi sette pattern.
1. Cache di npm/pnpm/yarn
actions/setup-node ha cache: 'pnpm' integrato. Per progetti con 600+ dipendenze: 3 minuti → 35 secondi sull'install.
2. Cache di Next.js / Vite build
Cache della cartella .next/cache o node_modules/.vite:
- uses: actions/cache@v4
with:
path: .next/cache
key: nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.{ts,tsx}') }}
3. Job paralleli, non sequenziali
Lint, type-check, test, build sono indipendenti. Stop a metterli in serie. Job separati che girano in parallelo: -50% sul tempo wall.
4. Test sharding
Vitest e Jest supportano --shard. Su una matrix con 4 shard, una suite da 8 minuti gira in 2.
5. Skip job inutili con paths-filter
Se la PR tocca solo docs/, perché far girare l'intero CI? Con dorny/paths-filter filtriamo prima e skippiamo i job non necessari.
6. Self-hosted runner per build pesanti
Per progetti con build superiori ai 10 minuti su runner standard, un self-hosted (anche su Hetzner CX31 a 12 €/mese) può dimezzare il tempo. Costo annuo < un mese di GitHub Pro extra minutes.
7. Concurrency lock per branch
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Push consecutivi cancellano le build precedenti — meno spreco, deploy più freschi.
Bonus
Misura sempre prima di ottimizzare. Il pannello Actions mostra il tempo per step. Spesso il problema è 1 step su 12 — non 12 step da accorciare.