Skip to content
th3chris
All posts
01From practice
13 min read

Static Code Analysis in the AI Age: Obsolete or Indispensable?

AICode QualityStatic AnalysisDevOpsSonarQubeAI Code Review.NET

Each new generation of coding models produces more code in less time, and the refrain in every other dev thread is the same: code now gets written faster than a human can read it. If a model stands up an entire service in a minute, why keep a static analyzer combing back over the same lines? Aren't SonarQube, SonarCloud and friends the fax machines of the dev-tool world, one step from extinction?

The short answer: no. The slightly longer one I'll argue here: precisely now, when AI multiplies code output, the deterministic quality gate becomes more valuable, not redundant. Whoever produces a lot has to verify a lot — with something that judges by fixed rules instead of guessing itself.

In short — An LLM writes code; a static analyzer judges every line reproducibly, on every commit, by the same rule. One doesn't replace the other. The AI accelerates, Sonar verifies. And that very separation is what keeps AI code at production grade.

The wrong question

"AI or static analysis" is a false dichotomy. The two don't solve the same problem — they sit at different points in the pipeline and have fundamentally different properties.

An AI review is context-rich but probability-based (probabilistic). It understands intent, spots "the code doesn't do what the comment promises," and reasons about business logic. But it isn't reproducible: the same diff, submitted twice, won't necessarily yield the same verdict. It usually sees only the diff, rarely the whole codebase. And it has no pass/fail a pipeline can hard-stop on.

A static analyzer is the opposite: context-poor but deterministic. Same rule, same line, same result — today, tomorrow, on every branch. It scans 100% of the codebase, not just the diff. It produces a hard quality gate that blocks in CI. And it records every measurement as a trend over months.

If both are needed, it pays to look closely at what each one contributes — and where one structurally fails while the other shines.

What an analyzer does that an LLM structurally can't

Four things no model, however good, can deliver by its nature:

Reproducibility. A statement like "this release contains no new Blocker-severity vulnerabilities" must come out the same every time you repeat it — otherwise it holds up neither in an audit, nor in a contract, nor in front of a customer. A deterministic scanner guarantees that. A sample from a probability model doesn't.

Full coverage. Sonar analyzes the entire tree on every run. An AI reviewer typically gets the diff and a slice of context — anything outside the window goes unchecked. Across many services and a large codebase, "outside the window" is the default case, and that's exactly where a risk otherwise rides along unnoticed.

A hard gate. sonar.qualitygate.wait=true makes the pipeline wait for the verdict and abort when new issues breach the threshold. That's a binary, automatable decision that faulty code snags on before a human overlooks it. "The model is broadly okay with the PR" isn't.

Trend over time. Maintainability rating, coverage trajectory, security hotspots per sprint, duplication ratio — Sonar keeps these as a time series. An LLM has no project memory across sessions; it doesn't know whether tech debt has been climbing since March or falling. Sonar knows it to the day.

On top of that, the security dimension: taint analysis traces how untrusted input flows through the code into a SQL query or a shell call — across method boundaries, mapped to OWASP and CWE. That's reproducible, auditable security evidence, not "looks safe to me." And the more code is generated automatically, the more lines have to pass through exactly this filter.

AI writes fast — who reviews the volume?

Which brings us to the real lever. The four points above sound like "nice to have" as long as a human writes code at a manageable pace. With AI, that tips over.

When an AI-assisted team produces three to five times the code, reviewer capacity doesn't scale with it. Human review becomes the bottleneck, and the temptation to wave AI output through with "looks good, merge" grows. That's exactly when you need an objective, tireless gate that measures every single generated line by the same yardstick — whether a human wrote it at 3 a.m. or a model wrote it in 200 milliseconds. It isn't what slows AI speed down; it's what makes AI speed accountable in the first place. Without it, more output is simply more unverified risk.

I use AI heavily in my own development. But everything generated runs through the same SonarQube instance as hand-written code — same rules, same gate. That's not distrust of the AI. It's the very reason I can hand the AI that much code at all. What that looks like concretely is the next example.

In practice: a product of my own

One of my own products — an AI nutrition assistant — is built in .NET, with several backend services and apps for web, iOS, Android and watch. Each service and app has its own SonarQube project, all running against a self-hosted SonarQube instance in a Kubernetes cluster. No code leaves my infrastructure — for a privacy-sensitive use case, that isn't a detail, it's a prerequisite.

The backend scan sits behind the test jobs in GitLab CI so the scanner picks up the coverage reports:

dotnet sonarscanner begin \
  /k:backend \
  /d:sonar.host.url="$SONAR_HOST_URL" \
  /d:sonar.cs.opencover.reportsPaths="**/coverage.opencover.xml" \
  /d:sonar.coverage.exclusions="**/Program.cs,**/Migrations/**,**/Configuration/*Options.cs" \
  /d:sonar.pullrequest.key="$CI_MERGE_REQUEST_IID" \
  /d:sonar.qualitygate.wait=true

On merge requests the quality gate blocks — but it judges only the MR's changes, not the whole backlog of debt. Pre-existing debt never holds up an unrelated PR. That's the "Clean as You Code" principle: new code must be clean, the legacy is paid down separately and on a plan (SonarSource: Clean as You Code).

The project enforces strict code rules anyway — Sonar is the layer that applies them across the whole codebase and over time, not just locally at build. So far, so tidy. Until you discover this very setup can lie in a subtle, costly way.

A number that didn't add up

Here's the part the "just have the AI set it up" camp underrates. Standing up a scanner is trivial. Setting it up so it tells the truth is the real work — and the costliest mistake is invisible. It throws no error. It reports green and lies.

It started harmlessly: the pipeline was green, the quality gate satisfied. What made me look twice was a single number that didn't fit — a service I knew was almost fully tested came back at 46% coverage. The next run, with no code change at all, showed a different figure again. Coverage that drifts between runs with nothing changed isn't a measurement — it's a symptom.

The cause wasn't the tests; it was the layout of the pipeline. The Sonar job ran in the same workdir as the preceding build job. An incremental dotnet build then skips compilation of already-built projects — and SonarScanner for .NET only sees the files of the projects actually compiled inside its window. Whatever was skipped dropped silently out of the analysis: no Roslyn analyzers, no coverage, no trace in the report. Depending on what the previous job happened to have built, the analyzed codebase shrank — and the reported coverage with it, down to that 46% instead of the real ~97%.

The fix is, in the end, a single line: --no-incremental in the Sonar build forces a full compile, so every analyzer runs over every file. Load-bearing — one line, without which every number in the dashboard is fiction.

That's the core: static analysis is valuable precisely because it doesn't guess — but that value lives and dies with the configuration. And the same AI that generates the code is not the authority that should sign off on its own verification setup. That's the craftsmanship side. The other side is governance — best seen in the enterprise.

In practice: an enterprise engagement

In one of my enterprise engagements — an industrial group with many teams — the second half of the picture shows: not keeping one repo clean, but making quality repeatable across many teams. Here the .NET services run through Azure DevOps Pipelines, and the Sonar integration comes from a central, shared template repo (DevOps/sonar-templates) that every service pipeline pulls in as a resource:

resources:
  repositories:
  - repository: sonar_templates
    type: git
    name: 'DevOps/sonar-templates'
    ref: 'refs/heads/master'

The effect: quality profiles, gate thresholds and scanner setup are configured once, centrally — not copied into dozens of pipelines that slowly drift apart. One standard for all, changes happen in one place. A skipSonar parameter exists — as a deliberate, visible exception for special cases like hotfixes, not as a silent default where the check quietly disappears. And SonarLint ships with committed rule config (.sonarlint/) right in the IDE, so the same rules apply as you type, not only later in CI.

That's the difference between "a tool somebody once kicked off" and a maintained quality infrastructure: centrally versioned, consistent across teams, with audit trail and approvals around it. Concretely: the same quality bar in every repo, a traceable record for every audit, and no setup that walks out the door with the one person who wired it up. That layer is exactly what no model hands you on the side. Which closes the loop — to the question of how AI and Sonar actually work together.

Sonar and AI are complements, not competitors

Here's how I run both together, and how I recommend it:

AI model (LLM)Static analysis (Sonar)
Strengthintent, logic, context, speeddeterminism, full coverage, trend
Rolegenerate + explanatory reviewhard gate + security evidence
Finds"doesn't do what was meant""breaks rule X, new vulnerability Y"
Weaknessnot reproducible, diff-scopeddoesn't grasp intent, false positives

The AI generates and gives the fast, context-rich feedback. Sonar draws the deterministic, auditable line that holds in CI. Where Sonar produces false positives, the AI helps triage. Where the AI misses logic bugs, human review catches them — relieved by both tools, replaced by neither. More on the security side of this interplay in How AI agents leak credentials.

"But don't modern models avoid many of those findings themselves?"

They do — and it's the most honest counter-argument. The current generation of coding models already clears many classic Sonar findings at generation time: unused variables, obvious null dereferences, trivial code smells. But reading that as "so we don't need Sonar anymore" mistakes what the tool is actually for.

It's precisely this that shifts Sonar's value — away from the style and lint questions the model handles anyway, toward what a model structurally can't deliver: reproducibility, a hard gate, trend over time, auditable security evidence. The cheap findings disappear; the expensive ones — where reliability and provability matter — stay exactly where the deterministic scanner is indispensable. The tool doesn't become obsolete; it just moves to where it belongs.

Conclusion

In the end, two different jobs sit side by side: a model generates code, an analyzer verifies it. AI is making the first one cheap — the second remains, and with it the deterministic authority that says a hard no in CI when something breaks the rules.

How that goes wrong in practice is what the 46% episode showed. So I build these setups myself and keep them in shape — and that's exactly what lets me lean on AI for the fast part.


If you want AI speed in your delivery without giving up the quality and security gate — and need a setup that tells the truth instead of just glowing green — let's talk.

Next step

Tell me what's slowing you down.

No pitch, no sales pressure: you describe the situation, and I'll tell you honestly whether and how I can help — personally, from your region.

I've been building software for over 25 years. What matters to me is not how modern a technology sounds, but whether it turns into a reliable solution — which is why I combine architecture, implementation and operations instead of handing over responsibility at the seams.

More about my approach and background
Christian Daniel

Christian Daniel

Your point of contact — advises, builds and stays

25+
years of software engineering
6 years
longest client relationship
30+
enterprise projects — concept to operations
< 24 h
response to your enquiry
  1. Free initial conversation
  2. Honest assessment
  3. Transparent estimate
Explore a project idea
View the recruiter profile