Skip to content

Speed up /vulnerabilities and filtered /software/versions queries#45564

Draft
dantecatalfamo wants to merge 12 commits into
mainfrom
45415-vulnerability-and-versions-speed-imporvement
Draft

Speed up /vulnerabilities and filtered /software/versions queries#45564
dantecatalfamo wants to merge 12 commits into
mainfrom
45415-vulnerability-and-versions-speed-imporvement

Conversation

@dantecatalfamo
Copy link
Copy Markdown
Member

@dantecatalfamo dantecatalfamo commented May 15, 2026

Address 100% DB CPU spikes observed when paginating these endpoints with filters. Two root causes: cve_meta and vulnerability_host_counts lack indexes for the actual filter shapes, and ListVulnerabilities ran correlated scalar subqueries on every row of vulnerability_host_counts that matched the scope (1.1M rows examined per call).

Add three online indexes:

  • cve_meta(cisa_known_exploit, cve) for the exploit filter
  • cve_meta(cvss_score, cve) for the CVSS range filter
  • vulnerability_host_counts(global_stats, team_id, host_count, cve) for the scope filter on the vulnerabilities endpoint

Refactor ListVulnerabilities into a two-stage query: an inner query filters, sorts, and paginates vulnerability_host_counts (with an optional LEFT JOIN to cve_meta for sort/filter columns), and an outer query enriches only the paginated page with the created_at and source scalar subqueries. Net effect: the heavy subqueries run perPage times (~20-100) instead of millions. Sort-by-created_at falls back to the single-statement form since the sort key is itself the subquery result.

CountVulnerabilities drops the redundant DISTINCT (vhc.cve is already unique within a (global_stats, team_id) scope via the existing UNIQUE KEY) and only joins cve_meta when KnownExploit filtering is requested.

Related issue: Resolves #45415

Checklist for submitter

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    See Changes files for more information.
  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Database migrations

  • Checked schema for all modified table for columns that will auto-update timestamps during migration.
  • Confirmed that updating the timestamps is acceptable, and will not cause unwanted side effects.
  • Ensured the correct collation is explicitly set for character columns (COLLATE utf8mb4_unicode_ci).

Summary by CodeRabbit

  • Performance
    • Reduced latency for the vulnerabilities endpoint for faster, more responsive listings and filtering.
    • Improved performance for filtered software versions queries, delivering quicker search and filter results.
  • Tests
    • Added automated checks to verify the database performance improvements remain effective.

Review Change Stack

dantecatalfamo and others added 2 commits May 14, 2026 21:57
…5415)

Address 100% DB CPU spikes observed when paginating these endpoints with
filters. Two root causes: cve_meta and vulnerability_host_counts lack
indexes for the actual filter shapes, and ListVulnerabilities ran
correlated scalar subqueries on every row of vulnerability_host_counts
that matched the scope (1.1M rows examined per call).

Add three online indexes:
- cve_meta(cisa_known_exploit, cve) for the exploit filter
- cve_meta(cvss_score, cve) for the CVSS range filter
- vulnerability_host_counts(global_stats, team_id, host_count, cve)
  for the scope filter on the vulnerabilities endpoint

Refactor ListVulnerabilities into a two-stage query: an inner query
filters, sorts, and paginates vulnerability_host_counts (with an
optional LEFT JOIN to cve_meta for sort/filter columns), and an outer
query enriches only the paginated page with the created_at and source
scalar subqueries. Net effect: the heavy subqueries run perPage times
(~20-100) instead of millions. Sort-by-created_at falls back to the
single-statement form since the sort key is itself the subquery result.

CountVulnerabilities drops the redundant DISTINCT (vhc.cve is already
unique within a (global_stats, team_id) scope via the existing UNIQUE
KEY) and only joins cve_meta when KnownExploit filtering is requested.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 15, 2026

Codecov Report

❌ Patch coverage is 88.05970% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.73%. Comparing base (326436c) to head (ccd99a4).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
server/datastore/mysql/vulnerabilities.go 89.28% 10 Missing and 2 partials ⚠️
...ations/tables/20260515000600_AddVulnPerfIndexes.go 81.81% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #45564      +/-   ##
==========================================
- Coverage   66.74%   66.73%   -0.02%     
==========================================
  Files        2744     2745       +1     
  Lines      219316   219425     +109     
  Branches    10794    10794              
==========================================
+ Hits       146393   146427      +34     
- Misses      59698    59769      +71     
- Partials    13225    13229       +4     
Flag Coverage Δ
backend 68.55% <88.05%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dantecatalfamo dantecatalfamo marked this pull request as ready for review May 15, 2026 16:11
@dantecatalfamo dantecatalfamo requested a review from a team as a code owner May 15, 2026 16:11
Copilot AI review requested due to automatic review settings May 15, 2026 16:11
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves performance for vulnerability and filtered software version queries by adding supporting MySQL indexes and reducing expensive per-row vulnerability metadata subqueries during pagination.

Changes:

  • Refactors ListVulnerabilities into a paginated inner query plus outer metadata enrichment, with a legacy path for created_at sorting.
  • Optimizes CountVulnerabilities and adds performance indexes for CVE metadata and vulnerability host counts.
  • Adds a migration, schema updates, migration test, and changelog entry.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
server/datastore/mysql/vulnerabilities.go Refactors vulnerability listing SQL and count query behavior.
server/datastore/mysql/schema.sql Adds new index definitions and records the new migration.
server/datastore/mysql/migrations/tables/20260515000600_AddVulnPerfIndexes.go Adds the online index migration.
server/datastore/mysql/migrations/tables/20260515000600_AddVulnPerfIndexes_test.go Verifies the migration creates the expected indexes.
changes/45415-vulnerability-and-versions-speed-imporvement Adds the user-visible changelog entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR updates the changelog, adds composite indexes to cve_meta and vulnerability_host_counts with a non-blocking migration and test, and refactors ListVulnerabilities into a two-stage SQL plan (inner paginated select from vulnerability_host_counts with optional cve_meta join; outer enrichment adds created_at/source and EE cve_meta with deterministic tie-break). CountVulnerabilities is changed to COUNT(*) over vulnerability_host_counts with conditional cve_meta joins when KnownExploit is requested.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: speeding up /vulnerabilities and /software/versions queries through indexing and query refactoring.
Linked Issues check ✅ Passed All objectives from #45415 are met: three indexes added for filter shapes, ListVulnerabilities refactored to limit scalar subqueries to paginated page size, CountVulnerabilities optimized with DISTINCT removed and conditional joins.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing #45415 performance issues: indexing strategy, query refactoring, migration, schema updates, and supporting tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 45415-vulnerability-and-versions-speed-imporvement

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/datastore/mysql/vulnerabilities.go`:
- Around line 381-387: The outer ORDER BY only reapplies the primary sort key
and can reshuffle ties; modify the outer ordering code (the block that checks
vulnerabilitiesAllowedOrderKeys and calls outer.WriteString) to append a
deterministic tie-breaker (the cve column) to the ORDER BY clause — e.g. when
orderCol != "cve" add ", cve ASC" (preserving the chosen direction for the
primary key using opt.ListOptions.OrderDirection) so the outer ordering matches
the inner cursor ordering and prevents duplicate/missing rows across pages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 44813082-5121-412c-82fb-c0e6c9c495c0

📥 Commits

Reviewing files that changed from the base of the PR and between 3b47670 and 1916210.

📒 Files selected for processing (5)
  • changes/45415-vulnerability-and-versions-speed-imporvement
  • server/datastore/mysql/migrations/tables/20260515000600_AddVulnPerfIndexes.go
  • server/datastore/mysql/migrations/tables/20260515000600_AddVulnPerfIndexes_test.go
  • server/datastore/mysql/schema.sql
  • server/datastore/mysql/vulnerabilities.go

Comment thread server/datastore/mysql/vulnerabilities.go
dantecatalfamo and others added 3 commits May 15, 2026 14:59
@dantecatalfamo dantecatalfamo marked this pull request as draft May 15, 2026 20:13
@dantecatalfamo
Copy link
Copy Markdown
Member Author

Converting to draft until we have time to load test it next week

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/api/v1/fleet/software/versions and /api/v1/fleet/vulnerabilities - slow query performance and high database resource utilization

2 participants