Skip to content

feat(api): remove unused database indexes and improve new failed findings index#9904

Merged
vicferpoy merged 6 commits intomasterfrom
PROWLER-695-review-database-indexes-to-remove-unused-ones
Jan 28, 2026
Merged

feat(api): remove unused database indexes and improve new failed findings index#9904
vicferpoy merged 6 commits intomasterfrom
PROWLER-695-review-database-indexes-to-remove-unused-ones

Conversation

@vicferpoy
Copy link
Member

Description

Review and clean up database indexes: drop unused ones, add a targeted partial index for a hot query path.

Dropped indexes

Partitioned tables (0071 — standard RemoveIndex, cascades to partitions):

  • findings: gin_findings_search_idx, gin_find_service_idx, gin_find_region_idx, gin_find_rtype_idx, find_delta_new_idx
  • resource_finding_mappings: rfm_tenant_finding_idx

Non-partitioned tables (0072RemoveIndexConcurrently for zero-downtime):

  • resources: gin_resources_search_idx
  • resource_tags: gin_resource_tags_search_idx
  • scan_summaries: ss_tenant_scan_service_idx
  • compliance_overviews: comp_ov_cp_id_idx, comp_ov_req_fail_idx, comp_ov_cp_id_req_fail_idx
  • resource_scan_summaries: implicit resource_id index (via SeparateDatabaseAndState + raw SQL to allow DROP INDEX CONCURRENTLY on a db_index=True field)

Added index

  • find_tenant_scan_fail_new_idx on findings(tenant_id, scan_id) WHERE status='FAIL' AND delta='new'
    • Created on partitions first (0073), then attached to parent (0074) to avoid full-table lock
Query plan after the new index
SELECT COUNT(*) AS "__count"
FROM "findings"
WHERE ("findings"."tenant_id" = 292d7930-95b4-4216-8207-6f01af52f486
       AND "findings"."delta" = NEW
       AND "findings"."status" = FAIL
       AND "findings"."scan_id" IN
         (SELECT DISTINCT ON (U0."provider_id") U0."id"
          FROM "scans" U0
          WHERE (U0."state" = completed
                 AND U0."tenant_id" = 292d7930-95b4-4216-8207-6f01af52f486)
          ORDER BY U0."provider_id" ASC,
                   U0."inserted_at" DESC)
       AND "findings"."tenant_id" = 292d7930-95b4-4216-8207-6f01af52f486)
36.028999999999996ms
0 joins
Query Plan
Aggregate  (cost=117.16..117.17 rows=1 width=8)
  ->  Nested Loop  (cost=2.64..117.16 rows=1 width=0)
        ->  HashAggregate  (cost=2.50..2.51 rows=1 width=16)
              Group Key: u0.id
              ->  Unique  (cost=2.48..2.48 rows=1 width=40)
                    ->  Sort  (cost=2.48..2.48 rows=1 width=40)
                          Sort Key: u0.provider_id, u0.inserted_at DESC
                          ->  Seq Scan on scans u0  (cost=0.00..2.47 rows=1 width=40)
                                Filter: ((tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END AND (state = 'completed'::state))
        ->  Append  (cost=0.15..114.17 rows=48 width=16)
              ->  Index Only Scan using findings_2026_jan_find_tenant_scan_fail_new_idx on findings_2026_jan findings_1  (cost=0.15..56.81 rows=41 width=16)
                    Index Cond: ((tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid) AND (scan_id = u0.id))
                    Filter: CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END
              ->  Index Only Scan using findings_2026_feb_find_tenant_scan_fail_new_idx on findings_2026_feb findings_2  (cost=0.12..8.16 rows=1 width=16)
                    Index Cond: (tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid)
                    Filter: ((u0.id = scan_id) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END)
              ->  Index Only Scan using findings_2026_mar_find_tenant_scan_fail_new_idx on findings_2026_mar findings_3  (cost=0.12..8.16 rows=1 width=16)
                    Index Cond: (tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid)
                    Filter: ((u0.id = scan_id) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END)
              ->  Index Only Scan using findings_2026_apr_find_tenant_scan_fail_new_idx on findings_2026_apr findings_4  (cost=0.12..8.16 rows=1 width=16)
                    Index Cond: (tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid)
                    Filter: ((u0.id = scan_id) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END)
              ->  Index Only Scan using findings_2026_may_find_tenant_scan_fail_new_idx on findings_2026_may findings_5  (cost=0.12..8.16 rows=1 width=16)
                    Index Cond: (tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid)
                    Filter: ((u0.id = scan_id) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END)
              ->  Index Only Scan using findings_2026_jun_find_tenant_scan_fail_new_idx on findings_2026_jun findings_6  (cost=0.12..8.16 rows=1 width=16)
                    Index Cond: (tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid)
                    Filter: ((u0.id = scan_id) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END)
              ->  Index Only Scan using findings_2026_jul_find_tenant_scan_fail_new_idx on findings_2026_jul findings_7  (cost=0.12..8.16 rows=1 width=16)
                    Index Cond: (tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid)
                    Filter: ((u0.id = scan_id) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END)
              ->  Index Only Scan using findings_default_find_tenant_scan_fail_new_idx on findings_default findings_8  (cost=0.14..8.17 rows=1 width=16)
                    Index Cond: (tenant_id = '292d7930-95b4-4216-8207-6f01af52f486'::uuid)
                    Filter: ((u0.id = scan_id) AND CASE WHEN (current_setting('api.tenant_id'::text, true) IS NULL) THEN false ELSE (tenant_id = (current_setting('api.tenant_id'::text))::uuid) END)

Bug fix

  • db_utils.create_index_on_partitions: use schema_editor.connection instead of bare connection import

Checklist

Community Checklist
  • This feature/issue is listed in here or roadmap.prowler.com
  • Is it assigned to me, if not, request it via the issue/feature in here or Prowler Community Slack

SDK/CLI

  • Are there new checks included in this PR? Yes / No
    • If so, do we need to update permissions for the provider? Please review this carefully.

UI

  • All issue/task requirements work as expected on the UI
  • Screenshots/Video of the functionality flow (if applicable) - Mobile (X < 640px)
  • Screenshots/Video of the functionality flow (if applicable) - Table (640px > X < 1024px)
  • Screenshots/Video of the functionality flow (if applicable) - Desktop (X > 1024px)
  • Ensure new entries are added to CHANGELOG.md, if applicable.

API

  • All issue/task requirements work as expected on the API
  • Endpoint response output (if applicable)
  • EXPLAIN ANALYZE output for new/modified queries or indexes (if applicable)
  • Performance test results (if applicable)
  • Any other relevant evidence of the implementation (if applicable)
  • Verify if API specs need to be regenerated.
  • Check if version updates are required (e.g., specs, Poetry, etc.).
  • Ensure new entries are added to CHANGELOG.md, if applicable.

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@vicferpoy vicferpoy requested a review from a team as a code owner January 28, 2026 10:43
@github-actions github-actions bot added component/api review-django-migrations This PR contains changes in Django migrations labels Jan 28, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 28, 2026

✅ All necessary CHANGELOG.md files have been updated.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 28, 2026

Conflict Markers Resolved

All conflict markers have been successfully resolved in this pull request.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 28, 2026

🔒 Container Security Scan

Image: prowler-api:7a0f516
Last scan: 2026-01-28 10:54:59 UTC

📊 Vulnerability Summary

Severity Count
🔴 Critical 11
Total 11

10 package(s) affected

⚠️ Action Required

Critical severity vulnerabilities detected. These should be addressed before merging:

  • Review the detailed scan results
  • Update affected packages to patched versions
  • Consider using a different base image if updates are unavailable

📋 Resources:

@codecov
Copy link

codecov bot commented Jan 28, 2026

Codecov Report

❌ Patch coverage is 93.47826% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.09%. Comparing base (5407f3c) to head (0e042f4).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9904      +/-   ##
==========================================
+ Coverage   85.97%   93.09%   +7.11%     
==========================================
  Files         222      197      -25     
  Lines        5689    26600   +20911     
==========================================
+ Hits         4891    24762   +19871     
- Misses        798     1838    +1040     
Flag Coverage Δ
api 93.09% <93.47%> (?)
prowler-py3.10-azure ?
prowler-py3.11-azure ?
prowler-py3.12-azure ?
prowler-py3.9-azure ?

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

Components Coverage Δ
prowler ∅ <ø> (∅)
api 93.09% <93.47%> (∅)
🚀 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.

@vicferpoy vicferpoy merged commit 8783e96 into master Jan 28, 2026
36 checks passed
@vicferpoy vicferpoy deleted the PROWLER-695-review-database-indexes-to-remove-unused-ones branch January 28, 2026 11:35
HugoPBrito pushed a commit that referenced this pull request Jan 29, 2026
Hamza-abughazaleh pushed a commit to Raed-sh/prowler that referenced this pull request Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/api review-django-migrations This PR contains changes in Django migrations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants