askill
salsa-overview

salsa-overviewSafety 100Repository

Start here for Salsa — the incremental computation framework for Rust. Use when asking what Salsa is, how it works, getting started, or seeking guidance on which specialized Salsa skill to load. Triggers on: #[salsa::db], #[salsa::input], #[salsa::tracked], #[salsa::interned], #[salsa::accumulator], salsa::Storage, memoization, incremental computation, dependency tracking, revisions, backdating, and the red-green algorithm.

1 stars
1.2k downloads
Updated 2/21/2026

Package Files

Loading files...
SKILL.md

Salsa: Incremental Computation for Rust

Salsa is a framework for incremental recomputation. You define inputs and pure functions over them. Salsa memoizes every function call. When inputs change, it re-executes only the functions whose dependencies actually changed — skipping everything else.

Salsa powers rust-analyzer (Rust IDE), ty (Python type checker), and Cairo, all of which need sub-second response times on large codebases after small edits.

The Mental Model

                    Salsa Database
                    ┌─────────────────────────────────────┐
 External world     │                                     │
 (editor, CLI,      │  Inputs ──→ Tracked Fns ──→ Output  │
  filesystem)       │    │            │                    │
        │           │    └── memoized ┘                    │
        │           │    dependencies tracked automatically│
        ▼           └─────────────────────────────────────┘
  Mutate inputs             │
  (new revision)            ▼
                    Only re-run what changed

The core loop:

let db = MyDatabase::default();

// 1. Create inputs
let file = SourceFile::new(&db, "fn main() {}".into(), path);

// 2. Compute (Salsa memoizes everything)
let result = analyze(&db, file);

// 3. Mutate an input (starts a new "revision")
file.set_text(&mut db).to("fn main() { 42 }".into());

// 4. Re-compute — Salsa reuses what it can
let result = analyze(&db, file);  // Only re-runs what depends on text

Core Concepts

The Database

A struct with #[salsa::db] that stores all cached data. It's the single source of truth — every Salsa operation takes a &db or &mut db.

#[salsa::db]
#[derive(Default, Clone)]
pub struct Database {
    storage: salsa::Storage<Self>,
}

#[salsa::db]
impl salsa::Database for Database {}

→ Patterns: load salsa-database-architecture for layered traits, test vs production, and side tables.

Inputs — The Roots

External data entering the system. The only mutable Salsa structs. Just newtypes around integer IDs (Copy, no lifetime).

#[salsa::input]
pub struct SourceFile {
    #[returns(ref)]
    pub text: String,
    pub path: PathBuf,
}

Tracked Functions — The Computation

Pure functions whose results are memoized. Salsa records which inputs/fields each call reads. On re-execution, it checks if those dependencies changed.

#[salsa::tracked]
fn parse(db: &dyn Db, file: SourceFile) -> Ast<'_> {
    let text = file.text(db);  // dependency recorded
    // ... parse ...
    Ast::new(db, statements)
}

→ Patterns: load salsa-query-pipeline for return modes, LRU, no_eq, specify, and granularity.

Tracked Structs — Intermediate Entities

Created inside tracked functions. Have per-field change tracking. Carry a 'db lifetime.

#[salsa::tracked]
pub struct Function<'db> {
    #[id]
    pub name: Word<'db>,         // used for cross-revision matching
    #[tracked]
    #[returns(ref)]
    pub body: Expression<'db>,   // per-field tracking
}

Interned Structs — Cheap Equality

Same data → same integer ID. Used for identifiers, type representations, module paths. Carry a 'db lifetime.

#[salsa::interned]
pub struct Word<'db> {
    #[returns(ref)]
    pub text: String,
}

→ Patterns: load salsa-struct-selection for the decision framework (e.g., ty's "no tracked structs" vs rust-analyzer's "intern every definition").

Accumulators — Side-Channel Output

Report diagnostics from tracked functions without affecting the return value.

#[salsa::accumulator]
pub struct Diagnostics(Diagnostic);

// Inside a tracked function:
Diagnostics::push(db, Diagnostic { message: "type error".into(), .. });

→ Patterns: load salsa-accumulators.

Revisions and the Red-Green Algorithm

Every input mutation increments a revision counter. When you call a tracked function, Salsa checks its dependencies since the last cached result. If they changed, it re-executes; if the new result equals the old one (backdating), it stops propagation.

Durability — Optimization Hint

Inputs can be tagged with LOW, MEDIUM, or HIGH durability. When only LOW-durability inputs change, Salsa skips validating stable subgraphs.

→ Patterns: load salsa-durability.

Example & Routing

I want to...Load this skill
Choose between input, tracked, and internedsalsa-struct-selection
Design my tracked functions and query graphsalsa-query-pipeline
Structure my database with layered traitssalsa-database-architecture
Handle recursive/cyclic queriessalsa-cycle-handling
Support cancellation in an LSP or CLIsalsa-cancellation
Optimize with durability levelssalsa-durability
Test that incremental reuse actually workssalsa-incremental-testing
Control memory with LRU and no_eqsalsa-memory-management
Build an LSP server backed by Salsasalsa-lsp-integration
Report diagnostics via accumulatorssalsa-accumulators
Move from prototype to production scalesalsa-production-patterns
Access low-level plumbing and "Level 4" patternssalsa-advanced-plumbing

Key Vocabulary

  • Revision: A version of the database between input mutations.
  • Ingredient: Any Salsa-managed item (input, tracked struct, interned struct, tracked fn, accumulator).
  • Backdating: If a re-executed function produces the same result, it's marked unchanged to prevent downstream re-execution.
  • Red-green algorithm: Salsa's strategy for deciding what to re-execute.
  • Durability: A promise about how often an input changes.
  • LRU: Least Recently Used eviction for bounding cache size.
  • no_eq: Skip equality comparison on result — always propagate changes.
  • Cycle: When tracked functions form a dependency loop.

Real-World Scale

  • ty: 2 inputs, 0 tracked structs for types (all interned), 60+ cycle sites.
  • rust-analyzer: 5+ inputs, tracked structs for collection caches, 6-layer DB hierarchy.
  • Cairo: 4 singleton inputs, 127+ tracked functions, 29 cycle sites, parallel compilation via CloneableDatabase.
  • django-language-server: 1 input, 2 accumulators, 5-layer DB (~78 Rust files — very approachable).
  • BAML: 15 tracked structs, 6-layer DB, documented early cutoff strategies.
  • Fe: marker traits for compilation phase enforcement, hybrid accumulator/return-value diagnostics.
  • stc [Legacy API]: 7 tracked functions wrapping the SWC TypeScript ecosystem — the "thin Salsa shell" approach to incrementalizing an existing tool.
  • wgsl-analyzer [Legacy API]: ~30 queries across 4 layers (~110 Rust files) — validates the rust-analyzer LSP architecture in a GPU shader language.
  • Mun [Legacy API]: ~40 queries across 6 query groups (~150 Rust files) — the only project extending Salsa through LLVM codegen to shared library output, with a hot-reloading compiler daemon.

The hardest part of Salsa is the design decisions about granularity, identity, and what to track. django-language-server and BAML are the best starting points for learning. stc [Legacy API] is the best example of wrapping an existing non-Salsa library with minimal Salsa code. Mun [Legacy API] is the best example of extending Salsa queries all the way to machine code generation and hot reloading.

Further Reading

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

90/100Analyzed 2/23/2026

High-quality overview skill for the Salsa incremental computation framework. Provides excellent mental model via ASCII diagram, comprehensive coverage of core concepts with code examples, clear routing table to 12 specialized skills, and real-world scale examples from major projects (rust-analyzer, ty, Cairo). The header includes explicit trigger conditions. Minor issues: tags are mismatched (ci-cd, linting, testing irrelevant to Salsa). Well-suited as an entry point for developers learning about incremental computation in Rust.

100
92
88
85
90

Metadata

Licenseunknown
Version-
Updated2/21/2026
Publisherjoshuadavidthomas

Tags

apici-cddatabasegithublintingtesting