Single-cell RNA-seq analysis: a best-practice workflow from FASTQ to figures
A step-by-step scRNA-seq workflow: alignment, empty droplets, ambient RNA, doublets, QC, integration, annotation, pseudobulk DE and trajectories.
Key takeaways
- Remove technical artifacts (empty droplets, ambient RNA, doublets) before clustering, or they become clusters.
- Set QC thresholds per sample with data-driven cutoffs, not one global mitochondrial percentage.
- Benchmark integration: the goal is to remove batch while keeping biological differences between conditions.
- Annotate with markers and biology; cluster numbers are not cell types.
- Compare conditions with pseudobulk or mixed models. The biological replicate, not the cell, is the unit of inference.
Single-cell RNA sequencing (scRNA-seq) measures gene expression in thousands to millions of individual cells. The data is sparse and noisy, and full of technical artifacts that look like biology. A sound analysis removes those artifacts first, then asks biological questions with statistics that respect the experimental design.
This guide describes the workflow our bioinformaticians and cell biologists use for 10x Genomics Chromium and similar droplet or combinatorial-indexing data. It follows the community best practices summarized by Luecken and Theis and, more recently, Heumos and colleagues, plus what we have learned from rescuing analyses that did not survive peer review.
Step 1: Alignment and counting
Start from FASTQ (or BCL) files when you can. Re-running alignment lets you confirm the chemistry, the reference genome and annotation version, and whether intronic reads were counted.
- Cell Ranger is the 10x reference implementation and the safest default for 10x data.
- STARsolo, alevin-fry and kallisto|bustools are faster, open alternatives with near-identical results when configured to match.
- For single-nucleus RNA-seq, include intronic reads. Most nuclear transcripts are unspliced, and excluding introns throws away much of the signal.
Record the reference build (for example GRCh38 with a specific GENCODE release). Mixing references across samples is a quiet source of batch effects.
Step 2: Separate cells from empty droplets
Most barcodes in a droplet experiment are empty droplets that contain only ambient RNA. Simple knee-point thresholds discard real cells with low RNA content, such as neutrophils, quiescent cells and many nuclei. Statistical methods such as EmptyDrops test each barcode against the ambient profile and recover these cells.
Step 3: Correct ambient RNA
Free-floating transcripts from lysed cells end up in every droplet. In practice this means hemoglobin genes in every blood-adjacent sample, immunoglobulin transcripts in every cell near plasma cells, and tissue-specific secreted genes everywhere. Uncorrected, ambient RNA:
- creates false marker expression (for example "T cells" expressing LYZ),
- produces spurious differential expression when ambient levels differ between samples, and
- blurs cluster boundaries.
CellBender and SoupX both estimate and remove the ambient profile. We run correction per sample and check that known lineage-exclusive markers become mutually exclusive afterwards.
Step 4: Detect and remove doublets
Doublets are droplets that captured two cells. Heterotypic doublets, made of two different cell types, co-express markers from both and often form small "intermediate" clusters that look like transitional states. scDblFinder and DoubletFinder simulate artificial doublets and score each barcode's similarity to them. Run detection per sample, because doublets only form within a capture lane.
What our experts avoid: naming a cluster that co-expresses markers of two lineages before ruling out doublets. It is the single most common error we find in rescued single-cell projects. See our case study on a "novel" population that was doublets.
Step 5: Quality control with adaptive thresholds
Classic QC metrics are counts per cell, genes per cell and the fraction of mitochondrial reads. The mistake is applying one fixed cutoff, such as "under 10% mitochondrial", to every sample and cell type. Metabolically active cells (cardiomyocytes, hepatocytes, some tumor cells) have high mitochondrial fractions for real biological reasons. Damaged cells in a poor sample can sit under any fixed cutoff.
We use per-sample thresholds based on the median absolute deviation (MAD), typically 3 to 5 MADs. We then check the removed cells: are they concentrated in one cell type? If so, the threshold is removing biology.
Step 6: Normalization and feature selection
- Shifted log normalization (counts per cell scaled to a common size, then log1p) works well for most analyses.
- scran pooling size factors handle heterogeneous populations better.
- SCTransform (regularized negative binomial regression) is a strong choice in Seurat workflows.
Select 2,000 to 5,000 highly variable genes for dimensionality reduction. Compute them per batch and combine, so one sample's variation does not dominate.
Step 7: Integration across samples
With multiple samples, technical differences (capture date, chemistry lot, sequencing depth) separate cells by sample rather than by biology. Integration methods align samples in a shared space:
| Method | Approach | When we use it |
|---|---|---|
| Harmony | Iterative correction of PCA embeddings | Fast default for moderate batch effects |
| scVI / scANVI | Deep generative model of counts | Complex designs, many batches, atlas mapping |
| Seurat v5 integration | Anchors, CCA/RPCA | Seurat-native workflows |
| BBKNN | Batch-balanced neighbor graph | Very large datasets |
Benchmarks by Luecken and colleagues show that no method wins everywhere. We score integration with batch removal and biological conservation metrics (scIB), and we check that condition-specific populations still separate. Over-correction can erase the very biology you are testing. Our integration guide covers this in depth.
Step 8: Clustering
Build a k-nearest-neighbor graph on the integrated embedding and cluster with the Leiden algorithm. The resolution parameter decides how many clusters you get, so treat it as a decision. We cluster at several resolutions, follow how clusters split with a clustering tree, and check stability by subsampling. Clusters that appear only at one resolution, or that are defined by stress or cell-cycle genes, need a closer look before they are named.
UMAP and t-SNE are visualization tools. Distances between clusters on a UMAP are not meaningful, so never draw biological conclusions from cluster positions on the plot.
Step 9: Cell-type annotation
Good annotation combines three sources of evidence:
- Canonical markers checked by a biologist, with literature support for each label.
- Reference mapping onto published atlases with tools such as Azimuth, CellTypist or scArches.
- Biological plausibility: does this cell type belong in this tissue, in these proportions?
Annotate hierarchically: major lineages first, then subcluster each compartment. Attach a confidence level to each label. "Activated fibroblast, high confidence" and "possible transitional state, low confidence" are both honest and useful.
Step 10: Compare conditions correctly
This is where most published single-cell errors happen. Cells from the same donor are not independent. Testing 5,000 cells from three mice against 5,000 cells from three other mice with a cell-level Wilcoxon test inflates significance enormously. Squair and colleagues showed that pseudobulk methods, which aggregate counts per sample and cell type before testing, consistently outperform cell-level tests in false discovery control.
- Differential expression: pseudobulk with DESeq2, edgeR or limma-voom, or mixed models with a donor random effect. See our pseudobulk guide.
- Differential abundance: test composition changes with Milo (neighborhood-level), scCODA (compositional) or propeller, not with raw proportions.
Step 11: Downstream biology
With clean, annotated data and correct comparisons, add the analyses that answer your question:
- Trajectories and pseudotime (Slingshot, PAGA, Monocle 3, Palantir) for differentiation and activation processes.
- RNA velocity (scVelo) and fate mapping (CellRank). Treat velocity as a hypothesis, since its kinetic assumptions often fail.
- Gene regulatory networks (pySCENIC) and TF activity (decoupleR).
- Cell-cell communication (LIANA, CellChat, NicheNet). Different resources and methods disagree, so we use consensus approaches and compare conditions rather than reporting raw interaction lists.
- Gene programs (cNMF, Hotspot) for continuous states that clusters split arbitrarily.
Step 12: Deliver reproducible results
A finished analysis is more than figures. It should include annotated objects (h5ad and Seurat), versioned code, software versions, parameters for every step, and a methods section that a reviewer can follow. Our deliverables include all of these by default, plus unlimited figure customization for journal formatting.
How OmicsQuest can help
Our duo teams run this workflow from FASTQ or from your existing objects, and frequently re-analyze datasets during peer review. See our single-cell RNA-seq analysis service for the full list of analyses, or read the 12 most common scRNA-seq mistakes we fix.
Frequently asked questions
What is the standard workflow for single-cell RNA-seq analysis?
Alignment and counting, empty-droplet calling, ambient RNA correction, doublet removal, per-sample QC filtering, normalization, feature selection, dimensionality reduction, integration across samples, clustering, annotation, then condition comparisons (pseudobulk differential expression and differential abundance) and optional trajectory, regulatory and cell-cell communication analyses.
Should I use Seurat or Scanpy?
Both are mature and produce equivalent results when used carefully. Seurat (R) integrates well with Bioconductor statistics; Scanpy (Python) scales well and connects to scvi-tools and deep-learning methods. We use both and convert objects between them as needed.
How many cells do I need per sample?
For most tissue studies, 3,000 to 10,000 high-quality cells per sample is enough to resolve major populations. Rare populations below 1% need more cells, and condition comparisons need more biological replicates more than they need more cells.
Work with OmicsQuest. Related services:
References
- Luecken MD, Theis FJ. Current best practices in single-cell RNA-seq analysis: a tutorial. Mol Syst Biol. 2019;15:e8746.
- Heumos L, Schaar AC, Lance C, et al. Best practices for single-cell analysis across modalities. Nat Rev Genet. 2023;24:550-572.
- Lun ATL, Riesenfeld S, Andrews T, et al. EmptyDrops: distinguishing cells from empty droplets in droplet-based single-cell RNA sequencing data. Genome Biol. 2019;20:63.
- Fleming SJ, Chaffin MD, Arduini A, et al. Unsupervised removal of systematic background noise from droplet-based single-cell experiments using CellBender. Nat Methods. 2023;20:1323-1335.
- Young MD, Behjati S. SoupX removes ambient RNA contamination from droplet-based single-cell RNA sequencing data. GigaScience. 2020;9:giaa151.
- Germain PL, Lun A, Garcia Meixide C, Macnair W, Robinson MD. Doublet identification in single-cell sequencing data using scDblFinder. F1000Research. 2021;10:979.
- McGinnis CS, Murrow LM, Gartner ZJ. DoubletFinder: doublet detection in single-cell RNA sequencing data using artificial nearest neighbors. Cell Syst. 2019;8:329-337.
- Hafemeister C, Satija R. Normalization and variance stabilization of single-cell RNA-seq data using regularized negative binomial regression. Genome Biol. 2019;20:296.
- Korsunsky I, Millard N, Fan J, et al. Fast, sensitive and accurate integration of single-cell data with Harmony. Nat Methods. 2019;16:1289-1296.
- Lopez R, Regier J, Cole MB, Jordan MI, Yosef N. Deep generative modeling for single-cell transcriptomics. Nat Methods. 2018;15:1053-1058.
- Luecken MD, Buttner M, Chaichoompu K, et al. Benchmarking atlas-level data integration in single-cell genomics. Nat Methods. 2022;19:41-50.
- Squair JW, Gautier M, Kathe C, et al. Confronting false discoveries in single-cell differential expression. Nat Commun. 2021;12:5692.
- Dann E, Henderson NC, Teichmann SA, Morgan MD, Marioni JC. Differential abundance testing on single-cell data using k-nearest neighbor graphs. Nat Biotechnol. 2022;40:245-253.
- Dimitrov D, Turei D, Garrido-Rodriguez M, et al. Comparison of methods and resources for cell-cell communication inference from single-cell RNA-Seq data. Nat Commun. 2022;13:3224.
- Bergen V, Lange M, Peidli S, Wolf FA, Theis FJ. Generalizing RNA velocity to transient cell states through dynamical modeling. Nat Biotechnol. 2020;38:1408-1414.
- Wolf FA, Angerer P, Theis FJ. SCANPY: large-scale single-cell gene expression data analysis. Genome Biol. 2018;19:15.
- Hao Y, Stuart T, Kowalski MH, et al. Dictionary learning for integrative, multimodal and scalable single-cell analysis. Nat Biotechnol. 2024;42:293-304.