Stop Legacy Debt from Growing with SonarQube New Code Gates
Scope SonarQube Quality Gates to new code so legacy issues do not block modern pull requests.
30 Nov 2025, 06:23 UTC

Enabling SonarQube on a legacy repository often produces an immediate wall of issues: thousands of bugs, security hotspots, and uncovered lines written years ago. If the Quality Gate is applied to the whole project, every pull request can fail because of code the current team never touched. The practical fix is to scope the gate to New Code only, so the pipeline blocks regressions while legacy debt is addressed separately.
Defining New Code in SonarQube
SonarQube calculates New Code separately from overall code. The definition is set in Project Settings > General Settings > New Code and determines which lines count toward Quality Gate thresholds. Common options include:
- Previous version: code changed since the last released version.
- Specific date: code changed after a chosen date.
- Branch: code introduced in the feature branch compared to the target branch.
For teams using pull requests, the Branch definition is usually the best starting point because it measures only what a developer is adding or changing right now.
Worked Example: Quality Gate for New Code
Assume a SonarQube project key of legacy-webapp and a Git branch workflow. Create a Quality Gate with the following conditions, all scoped to New Code:
| Metric | Scope | Threshold | Effect |
|---|---|---|---|
| Bugs on New Code | New Code | 0 | Blocks new defects |
| Vulnerabilities on New Code | New Code | 0 | Blocks new security flaws |
| Security Hotspots on New Code | New Code | 100% reviewed | Requires manual review of risky patterns |
| Coverage on New Code | New Code | At least 80% | Ensures changed logic has tests |
| Duplication on New Code | New Code | Less than 3% | Limits copied blocks in changed files |
Attach this gate to the legacy-webapp project. When a pull request is analyzed, SonarQube evaluates only the lines changed in that branch against these thresholds.
Enforcing the Gate in CI
Run the scanner on the CI runner, not a developer laptop, so the result is consistent and cannot be skipped locally. The CI job needs the SONAR_TOKEN environment variable with permission to analyze the project and read the quality gate status. Use a service account token rather than a personal access token so the pipeline continues to work if a team member leaves.
sonar-scanner -Dsonar.projectKey=legacy-webapp -Dsonar.sources=. -Dsonar.host.url=https://sonar.example.com -Dsonar.login="$SONAR_TOKEN" -Dsonar.qualitygate.wait=true
The -Dsonar.qualitygate.wait=true property makes the scanner pause until SonarQube finishes processing the report. If the gate fails, the scanner exits with a non-zero code, which fails the CI job and prevents the merge. The runner must have network access to the SonarQube server, and the job should allow enough time for asynchronous analysis; otherwise the step can time out before a status returns.
Checking the Result
After the scan, open the project in SonarQube and select the Quality Gate tab. The dashboard shows whether the gate passed or failed and lists the specific metric that caused the failure. If a pull request fails because of Coverage on New Code, the fix is to add tests for the changed lines, not to lower the gate for the whole repository.
Limitation
A New Code gate stops debt from growing, but it does not reduce existing debt. A legacy file with no tests can still be modified as long as the new lines meet coverage, which may leave risky code untouched. Also, overly strict coverage thresholds can encourage low-value tests written only to satisfy the gate. Review the Quality Gate trend weekly and adjust thresholds if developers are gaming metrics instead of improving code.
Next Step
Start with the Branch definition and a gate that allows zero new bugs and vulnerabilities. Run it in warning-only mode for one sprint, then switch to blocking. Once the gate is stable, create a separate plan for legacy issues, such as fixing files in order of churn or criticality, outside the pull request gate.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.