# salmon 2.0: a Rust rewrite that kept the old interface and changed the index

> salmon is a transcript level quantification tool for RNA-seq that pairs selective alignment with an EM based inference over equivalence classes. Version 2.0 rewrote it in Rust from scratch, kept the salmon index, salmon quant, quant.sf workflow, and broke the index format, so every existing index has to be rebuilt.

**COMBINE-lab/salmon** — 🐟 🍣 🍱 Highly-accurate & wicked fast transcript-level quantification from RNA-seq reads using selective alignment

- Repository: https://github.com/COMBINE-lab/salmon
- Website: https://combine-lab.github.io/salmon
- Stars: 943 · Forks: 192
- Language: Rust
- License: BSD-3-Clause
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/combine-lab-salmon

## Transcript level estimates from reads or from unsorted alignments

salmon answers one question: how much of each transcript is present in an RNA-seq sample. The description calls it transcript level quantification, which is the distinction that matters against a genome level counter. The input is either raw sequencing reads or regular alignments to the transcriptome, provided as an unsorted BAM, and the same inference engine runs either way.

The audience is anyone running bulk RNA-seq on a transcriptome, particularly people who want per-transcript numbers without writing an alignment and counting pipeline themselves. The output lands in a file the ecosystem already knows: `quant.sf`, described as a drop-in for tximport, tximeta, fishpond and swish. That compatibility is the practical reason to care about the tool rather than writing a custom pipeline, because downstream differential expression tooling reads the file without changes.

The homepage lives at combine-lab.github.io/salmon and the docs there cover installation, library types, the difference between selective alignment and sketch mode, inferential replicates, the migration guide, a CLI reference and a specification of every output file. The README is a short front door to that documentation rather than a manual, so the depth of the tool sits behind the site.

## Selective alignment, sketch mode and EM over equivalence classes

The mechanism has two halves. The first is a fast mapping stage, which can be selective alignment or an alignment-free sketch mode invoked with `--sketch`. The second is a massively parallel statistical model, described as EM and VBEM over equivalence classes, that estimates transcript abundances from the mapped result.

Equivalence classes are the key idea. Instead of resolving every read to a single transcript, the mapper records the set of transcripts a read is compatible with, and the inference stage solves for abundances consistent with those sets. That is what makes the approach tolerant of reads shared between similar transcripts, and it is why the empirical Bayes variant appears in the description rather than a plain EM.

The library type is a first class parameter rather than an afterthought. In the quick start the `-l A` flag is used and the README comments that this auto-detects the library type. Paired versus single ended, stranded or not, all affect the likelihood model, and the docs page for library types exists precisely because getting this wrong quietly biases the result.

For bulk RNA-seq the inference engine does the heavy lifting. For single-cell work, that path was removed: the README states that single-cell quantification moved to the alevin-fry ecosystem and that `salmon alevin` is gone. If your experiment is single-cell, this version of salmon is no longer the right entry point.

## Four install routes, and the sample data that walks through the workflow

salmon 2.0 ships as a single portable binary with no compiler, Boost or system libraries required. The README offers four ways to get it, and the first one is a prebuilt binary installer covering Linux and macOS on x86-64 and aarch64:

```sh
# install script (prebuilt binaries: Linux & macOS, x86-64 & aarch64)
curl --proto '=https' --tlsv1.2 -LsSf \
  https://github.com/COMBINE-lab/salmon/releases/latest/download/salmon-cli-installer.sh | sh

# or via cargo (Rust ≥ 1.91)
cargo install salmon-cli

# or via conda
conda install -c bioconda -c conda-forge salmon

# or Docker
docker run --rm combinelab/salmon:latest salmon --version
```

For a first real use, the repository ships `sample_data.tgz`, and the README's quick start unpacks it and builds an index and then a quantification:

```sh
# 0) Unpack the sample data and go to it
tar xzf sample_data.tgz
cd sample_data

# 1) build a reusable index from a transcriptome
salmon index -t transcripts.fasta -i salmon_index -p 16

# 2) quantify (-l A auto-detects the library type)
salmon quant -i salmon_index -l A \
  -1 reads_1.fastq -2 reads_2.fastq -p 4 -o sample_quant
```

Three things are worth reading off that snippet. The index is built once from a transcriptome and reused, which is the whole point of the two step design across many samples. The `-p` flag is the thread count, set to 16 for indexing and 4 for the quantification here. And the output directory name, `sample_quant`, is the `-o` value, so results land in `sample_quant/quant.sf`.

## The index format changed, so 1.x indexes cannot be reused

This is the headline caveat and the README puts it in an IMPORTANT block at the top. salmon 2.0 is a from-scratch Rust rewrite of the C++ program. It keeps the same workflow of `salmon index` then `salmon quant` then `quant.sf`, and it keeps the output formats that downstream tools read, but it is a new major version with breaking changes. The most important one is that the index format changed, so the index must be rebuilt. MIGRATION.md in the repository holds the full list of changed, removed and new options.

That has an operational cost that is easy to underestimate. A pipeline that built an index once, cached it, and reused it across runs will now either fail or produce garbage unless the cache is invalidated. Rebuilding an index is not free in wall clock time for large transcriptomes, and the sample workflow shows indexing taking a separate step of its own with its own thread allocation.

The older line is not dead. The final C++ release, salmon 1.12.0, lives on the `cpp` branch of the same repository and remains installable as the `salmon-cpp` conda package. That gives a migration path for environments that cannot yet move, and it is worth knowing that the C++ branch is where 1.x development stopped rather than where it continues.

The rewrite also changes the packaging story. The README states that salmon 2.0 ships as a single portable binary, with no compiler, Boost or system libraries to install, which is a real gain over a C++ toolchain dependency.

## Decoy sequences absorb reads that would otherwise be misassigned

salmon can index decoy sequence alongside the transcriptome. The rationale given is that accounting for fragments of unexpected origin improves quantification: reads that would otherwise be spuriously assigned to a transcript are absorbed by the decoy instead. In practice this means the genome itself is often used as the decoy.

The mechanism is a file passed with `-d/--decoys`, with one hard constraint that catches people out: the decoy records must appear last in the FASTA. The decoy name file names those records, and the docs cover building a decoy-aware index.

The order requirement is not cosmetic. A FASTA in which the transcriptome comes first and the decoy follows is the layout the indexer expects, and mixing or interleaving the sequences changes what the index contains. Teams that already maintain decoy-aware references for other tools will have a FASTA to reuse, but the placement rule means you cannot simply append an arbitrary second FASTA to an existing file without checking the layout.

Worth being precise about what this does and does not do. It reduces spurious assignment of fragments that came from somewhere else in the genome. It is not a filter that discards low quality or contaminated reads, and it does not change the abundance model, which still runs over equivalence classes. The gain is in what the mapping stage stops misassigning.

## A Cargo workspace of ten crates, from mapping to inference

The repository is a Rust workspace, and Cargo.toml names the members. The pipeline is visible in the crate names: `salmon-index` builds the index, `salmon-map` and `salmon-align` handle mapping, `salmon-eqclass` deals with equivalence classes, `salmon-infer` and `salmon-model` cover inference, `salmon-quant` produces the quantification, `salmon-core` and `salmon-rad` hold shared pieces, and `salmon-cli` is the binary. Every internal crate is declared twice in the workspace dependencies, with a path for local builds and a version for `cargo publish`, so the same source can be built from a checkout and published independently.

The workspace pins Rust 1.91 as `rust-version` and uses edition 2021, with the version at 2.8.0. The shared dependency choices reveal where the time goes. `rayon` and the crossbeam crates handle parallelism, `dashmap` provides a concurrent map for equivalence classes, and `ahash` is described in the file comments as a fast, non-DoS-resistant hasher for hot per-read integer keyed maps. That last comment is an explicit statement that this is not a hash function chosen for adversarial resistance, which is a reasonable trade-off inside a trusted analysis pipeline and would be a poor choice in a service taking untrusted input.

The `crates/` layout also explains the Dockerfile, which is a multi-stage cargo build that copies the workspace, builds the binary crate in release mode with `--locked`, strips it and drops it into a slim Debian runtime image. The build relies on .cargo/config.toml, which pins a portable SIMD floor, with the alignment library still selecting AVX2, SSE4.1 or NEON at runtime. The runtime image is deliberately minimal, and its comments show that even `procps` is installed because Nextflow shells into the container and calls `ps` to collect task metrics, failing the task outright when that command is missing.

## Licence, release cadence and the citation to keep

The licence is BSD-3-Clause, stated in the README, in the Cargo.toml workspace package metadata and as an image label on the Docker build. That is a permissive licence with no copyleft obligation, which for a bioinformatics tool embedded in an academic or commercial pipeline is usually the easy case, though what you do with the outputs and with the genome reference you index is a separate question from the licence of the program.

Maintenance is active and visible. The last push was on 2026-10-19, and the recent release history shows v2.8.0 on 2026-09-25, v2.7.0 on 2026-08-30 and v2.6.0 on 2026-08-24. Three releases in a month is a fast cadence for a tool of this kind, and it means option names can move between minor versions, so MIGRATION.md and the CLI reference deserve a look each time you bump the version.

The README asks for a specific citation if you use salmon: Patro, Duggal, Love, Irizarry and Kingsford (2017), Salmon provides fast and bias-aware quantification of transcript expression, in Nature Methods, with the DOI 10.1038/nmeth.4197. The repository also carries a CODE_OF_CONDUCT.md, a CONTRIBUTING.md, a docs directory, a website directory, a notes directory and a scripts directory alongside the sample data archive.

## Conclusion

salmon 2.0 suits teams that quantify bulk RNA-seq and want transcript level estimates without writing their own alignment or EM pipeline, especially existing salmon 1.x users who already know the output files. It is the wrong choice for single-cell work, since the salmon alevin command was removed and that path now belongs to the alevin-fry ecosystem, and for anyone who cannot rebuild indexes, because the index format changed and a stale index is silently incompatible. Verify three things first: that your indexes are rebuilt with salmon 2.0 rather than reused, that your reads are paired FASTQ or an unsorted BAM as the inference engine expects, and that the workflow managers reading quant.sf, such as tximport or fishpond, still accept the Salmon 2.0 output format.

## FAQ

### How do I install salmon 2.0?

The README gives four routes: a prebuilt binary install script for Linux and macOS on x86-64 and aarch64, `cargo install salmon-cli` with Rust 1.91 or newer, `conda install -c bioconda -c conda-forge salmon`, and the Docker image `combinelab/salmon`. The project ships as a single portable binary with no compiler or system libraries needed.

### Do I need to rebuild my index after upgrading to salmon 2.0?

Yes. The README states that salmon 2.0 is a from-scratch Rust rewrite and that the index format changed, so an index built with the C++ 1.x line cannot be reused. MIGRATION.md lists the full set of changed, removed and new options.

### Can salmon still quantify single-cell RNA-seq data?

Not through this project. The README says single-cell quantification moved to the alevin-fry ecosystem and that the `salmon alevin` command was removed. Salmon 2.0 is aimed at bulk quantification from reads or an unsorted BAM.

### What is selective alignment and when should I use sketch mode instead?

Selective alignment is the fast mapping stage that pairs with the EM and VBEM inference over equivalence classes. The `--sketch` flag switches to an alignment-free sketch mode. The README does not give a decision rule between the two, and points to the documentation page covering selective alignment against sketch mode.

### What does salmon produce and what can read it?

Results land in the output directory as `quant.sf`, for example `sample_quant/quant.sf`. The README describes that file as a drop-in for tximport, tximeta, fishpond and swish.

### How do I add a decoy genome to the index?

Pass a decoy name file with `-d/--decoys`, and make sure the decoy records appear last in the FASTA. The decoy absorbs reads that would otherwise be assigned spuriously to a transcript, and the docs cover building a decoy-aware index.

## Sources

- [COMBINE-lab/salmon on GitHub](https://github.com/COMBINE-lab/salmon)
- [License: BSD-3-Clause](https://github.com/COMBINE-lab/salmon/blob/master/LICENSE)
- [Project website](https://combine-lab.github.io/salmon)
- [README](https://github.com/COMBINE-lab/salmon/blob/master/README.md)
- [Releases](https://github.com/COMBINE-lab/salmon/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/combine-lab-salmon
