Glossary · Single-Cell and Spatial
Clustering resolution
The number you tweak until the UMAP "looks right" is quietly deciding which cell types exist in your paper.
By Ming "Tommy" Tang, Director of Bioinformatics in Big Pharma · Reviewed September 2026 · 3 min read
Also: resolution parameter, FindClusters
Definition
Clustering resolution is the parameter that controls how aggressively a graph-based community-detection algorithm (Louvain or Leiden, as run by Seurat's FindClusters) partitions cells on the shared-nearest-neighbor graph. It scales the modularity function the algorithm optimizes: raise it and the algorithm rewards finer partitions with more, smaller clusters; lower it and it rewards coarser ones with fewer, larger clusters. It carries no absolute biological unit, the same resolution value produces a different cluster count on a different dataset, a different number of PCs, or a different k in the neighbor graph. Seurat's default is 0.8, which is a reasonable starting point, not a validated answer for your data.
You hit this parameter right after building the shared-nearest-neighbor graph, when you call FindClusters() and have to decide what number goes in the resolution argument. Run it at 0.5 and you get 23 clusters. Run it at 0.8 and you get 31. Nothing else about the data changed, only your guess at how finely to cut a continuous manifold into discrete boxes.
This is not a cosmetic choice. Resolution decides how many "cell types" exist in your analysis before you've looked at a single marker gene. Every downstream step, cluster annotation, differential expression between clusters, cell-type proportions across conditions, inherits whatever granularity you picked here. Get it wrong and you either merge two real subtypes into one blob or split one real subtype into two clusters that differ by nothing biological.
Why it matters
Pick a resolution that's too low and real subtypes disappear inside a bigger cluster: naive and memory T cells get labeled "T cells," and any biology that only differs between those two subsets is invisible to you. Pick one that's too high and you split a single coherent population, like monocytes, into two "clusters" that separate on noise rather than biology, a documented failure mode where resolution 1.0 splits monocyte subtypes that resolution 0.8 correctly keeps together.
The downstream cost compounds. If you cluster cells and then test for differentially expressed genes between the clusters you just created, you're double dipping: the clustering already used the expression differences to draw the boundary, so the DE test rediscovers them and hands you p-values as small as 1e-20 that reflect the clustering decision, not new biology. Oversplitting at high resolution manufactures more of these spurious "significant" boundaries, which is exactly the trap covered under [[p-value-cutoff]] thinking.
Where people get it wrong
The most common mistake is treating resolution as if it has one correct value waiting to be found, then defending whatever number produced a UMAP that "looks clean." There is no single optimal resolution for a dataset, cell populations are hierarchical (type, then subtype, then state), so the right resolution depends on which level of that hierarchy your question lives at, not on some property of the data alone.
A second mistake is leaving the default (0.8) unquestioned regardless of dataset size, when the useful range shifts with cell number: roughly 0.4, 1.4 works for 3,000, 5,000 cells, and larger datasets typically need higher resolution to resolve the same granularity. A third is forgetting that k.param (neighbors in the graph) and the number of PCs you feed into FindNeighbors change cluster granularity just as much as resolution does, so tuning resolution alone while leaving those fixed only tells you half the story. Silhouette scores also mislead on their own: a resolution can score well statistically while still splitting a population you can't tell apart on any marker gene, which is why marker-gene inspection has to accompany any numeric stability metric.
A concrete example
Instead of guessing a single resolution, run a small sweep, cross-tabulate the results, and check marker genes before trusting any of them. The workflow below mirrors testing 0.2, 0.5, 0.8, 1.0, and 1.5 on a PBMC dataset and comparing silhouette scores and known marker separation across the sweep, then confirming that going from 0.8 to 1.0 splits a population (e.g., monocytes) without a clean marker to justify it.
# Sweep resolutions instead of picking one
pbmc <- FindClusters(pbmc, resolution = c(0.2, 0.5, 0.8, 1.0, 1.5))
# Each resolution gets its own metadata column, e.g. RNA_snn_res.0.8
table(pbmc$RNA_snn_res.0.8, pbmc$RNA_snn_res.1)
# Before trusting a jump in cluster count, check whether it's backed
# by a marker, not just graph noise
FeaturePlot(pbmc, features = c("CD14", "FCGR3A"), split.by = "RNA_snn_res.1")Related terms
Questions people ask
- What resolution should I use in Seurat's FindClusters?
There's no fixed correct value. For 3,000-5,000 cells, 0.4-1.4 is a reasonable range to test, and larger datasets typically need higher resolution to resolve the same granularity. Sweep several values, cross-tabulate the resulting cluster assignments, and check whether each new split is backed by a marker gene before you keep it.
- Is resolution 0.5 or 1.0 better for scRNA-seq clustering?
Neither is universally better. 0.5 gives fewer, broader clusters; 1.0 gives more, finer ones. The right choice depends on whether your biological question needs major cell types or subtypes, and on how many PCs and how large a neighbor graph you built upstream.
- Why does higher resolution sometimes give worse clusters?
Higher resolution rewards the algorithm for finding more communities, which can split a single coherent population, like monocytes, into two clusters that differ on graph noise rather than expression. A high silhouette score doesn't rule this out, so pair any resolution sweep with a look at known marker genes.
- Does changing resolution affect differential expression results?
Yes, directly. If you cluster cells and then test for DE genes between the clusters you just made, you're double dipping: the test rediscovers the differences the clustering already used to draw the boundary, producing artificially tiny p-values. Oversplitting at high resolution manufactures more of these spurious boundaries.
- What is the default clustering resolution in Seurat?
Seurat's FindClusters defaults to resolution = 0.8. Values above 1.0 return more clusters, values below 1.0 return fewer. It's a starting point for exploration, not a value validated for your specific dataset.
Related pages
- Guide · How to Detect Batch Effects in Single-Cell ATAC-seq
- Guide · How to Find and Remove Doublets in Single-Cell ATAC-seq
- Guide · How to Find and Remove Doublets in Single-Cell RNA-seq
- Guide · How to Detect Integration Over-Correction in Single-Cell RNA-seq
- Guide · How to Choose a Normalization Method in Single-Cell RNA-seq
Related reading on the blog
Sources
- Seurat FindClusters Reference Documentation — Defines the resolution parameter, its default (0.8), and how it scales cluster count
- Bioconductor: Basics of Single-Cell Analysis - Chapter 5: Clustering — Explains why there is no single optimal resolution given the hierarchical nature of cell populations
- HBC Training: Single-Cell RNA-seq Clustering Analysis — Practical resolution ranges (0.4-1.4 for 3K-5K cells) and the multi-resolution sweep workflow
- Fine tune the best clustering resolution for scRNAseq data: trying out callback — Automated resolution selection methods and the need for biological validation of results