Using Codecov Flags and Carryforward to Keep Monorepo Coverage Accurate
Monorepos often hide coverage regressions; flags and carryforward let each component stay independent and up-to-date.
22 Jan 2026, 03:33 UTC

Why coverage numbers lie in a monorepo
In a repository that contains several independent projects, a single coverage percentage can hide problems in one package while another looks healthy. The CI check passes, but a developer may merge code that reduces test coverage for a critical component without noticing.
The thesis
Codecov's flags and carryforward features let you treat each component as its own coverage unit, set separate thresholds, and keep historical data alive across PR runs.
Define flags for each component
What is a flag?
A flag is a label you attach to a coverage upload. It groups lines of code under a named bucket such as frontend or shared-lib. The UI then shows a matrix where each flag has its own status badge and threshold.
Configuration example
# codecov.yml
coverage:
precision: 2
round: down
status:
project:
default:
target: 80%
patch:
default:
target: 0%
flags:
- name: frontend
paths:
- src/frontend/...
threshold: 80%
- name: backend
paths:
- src/backend/...
threshold: 90%
Here we create two flags. The paths field tells Codecov which directories belong to each flag. The threshold can be a project-wide target or a per-flag target.
How carryforward keeps baselines alive
Carryforward explained
When a PR touches only one flag, the other flags have no new coverage files. Carryforward automatically copies the most recent successful coverage data for those flags from the base branch (usually main). The PR comment therefore shows the previous baseline instead of "No coverage uploaded".
Practical impact
Consider a monorepo with frontend and backend flags. The frontend suite runs on every commit, while the backend suite runs only on the backend-service job. If a PR modifies only frontend files, the backend flag will show the last merged coverage from main. The PR status check will still verify the backend threshold against that baseline, preventing a false-negative.
Worked example: a PR that touches only one component
Setup
- Create a minimal monorepo with two packages:
pkg-aandpkg-b. - Add a
codecov.ymlas shown above, assigningpkg-ato thefrontendflag andpkg-bto thebackendflag. - In the CI matrix, run the
frontendjob withcodecov -F frontendand thebackendjob withcodecov -F backend.
Running a PR
Assume the base branch main has a successful build where both flags uploaded coverage:
# after merging main
codecov -F frontend # uploads 85% for pkg-a
codecov -F backend # uploads 92% for pkg-b
Now a developer opens a PR that modifies only pkg-a files. The frontend job uploads new data (88%). The backend job has no new files, so carryforward supplies the previous 92% value.
Verification steps
- Check the PR comment: it should display a table with two rows -
frontend(88% vs 85% baseline) andbackend(88% vs 92% baseline). - Confirm the status check passes for
frontendbecause 88% >= 80% threshold, and also passes forbackendbecause the carried-forward 92% still meets the 90% threshold. - If the
backendcoverage were truly lower (e.g., 88% after a silent failure), the status check would fail, alerting the reviewer.
Trade-offs and limitations
Flag limit
Codecov caps the number of flags at 50 per repository. Large monorepos may need to consolidate related packages under a single flag or migrate to the beta "Components" feature, which requires separate verification.
Masking regressions
Carryforward can hide a real drop in coverage if the base-branch data is stale or if flaky tests skip measurements. Pair carryforward with a required status check on the base branch that forces a fresh upload before the PR is merged.
Patch-mode nuance
When a threshold is set to patch mode, only lines changed in the PR are evaluated. Deleting a large amount of tested code can cause the overall project coverage to fall while the per-flag patch metric still passes. Monitor project-wide trends separately.
Actionable closing
To start using flags and carryforward:
- Define the flags you need in
codecov.yml, matching directory paths to each component. - Add
-F <flag>to every test suite that belongs to a flag. - Ensure the base branch has a successful build with each flag uploaded; this guarantees carryforward works.
- Review the PR comment matrix; verify that each flag's coverage meets its own threshold before merging.
- Periodically audit the flag list for duplication and watch the 50-flag ceiling.
With these steps, a monorepo can keep coverage numbers trustworthy, give reviewers precise context, and prevent hidden regressions.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.