DependencyTrack / DependencyTrack/dependency-track
High database load
- Dominant language
- Java
- Stars
- 4.2k
- Forks
- 811
- Avg merge
- 8h 39m
- Merged PRs (30d)
- 237
Description
### Current Behavior
While operating version 5.0.2 the system suddenly started to experience an ongoing extremely high database load.
The postgres process continuously uses all system cpu cores with 100%.
The drive space also fills up with a rate of about 10GB per 12 hours.
This persists after an restart.
An update to 5.0.3 did not bring any changes.
The system was originally set up with v4 and updated according to the migration guide. Afterwards it worked fine for about a month.
We only have about 10 projects on the system.
### Steps to Reproduce
1.Enabling query logging on the postgres docker image results in a continuos stream of these queries:
```
postgres-1 | 2026-07-29 06:15:28.852 UTC [53] DETAIL: Parameters: $1 = '{import-bom,identify-internal-components,resolve-package-metadata,update-portfolio-metrics,publish-notification,import-vex,process-scheduled-notifications,analyze-project,mirror-vuln-data-source,sync-vuln-policy-bundle,vuln-analysis}', $2 = '{00:01:00,00:01:00,00:01:00,00:01:00,00:01:00,00:01:00,00:05:00,00:01:00,00:01:00,00:01:00,00:01:00}', $3 = 'default', $4 = 'b0a114985503-ef800c59', $5 = '100', $6 = 'b0a114985503-ef800c59', $7 = 'default'
postgres-1 | 2026-07-29 06:15:28.852 UTC [53] LOG: execute S_1: COMMIT
postgres-1 | 2026-07-29 06:15:28.888 UTC [49] LOG: statement:
postgres-1 | 2026-07-29 06:15:28.890 UTC [49] LOG: statement: BEGIN
postgres-1 | 2026-07-29 06:15:28.890 UTC [49] LOG: execute S_3: SELECT pg_try_advisory_xact_lock($1)
postgres-1 | 2026-07-29 06:15:28.890 UTC [49] DETAIL: Parameters: $1 = '275439834778508297'
postgres-1 | 2026-07-29 06:15:28.892 UTC [49] LOG: execute S_4: WITH polled AS (
postgres-1 | SELECT "ID"
postgres-1 | FROM "NOTIFICATION_OUTBOX"
postgres-1 | ORDER BY "ID"
postgres-1 | LIMIT $1
postgres-1 | )
postgres-1 | DELETE
postgres-1 | FROM "NOTIFICATION_OUTBOX"
postgres-1 | WHERE "ID" IN (SELECT "ID" FROM polled)
postgres-1 | RETURNING "PAYLOAD"
postgres-1 |
postgres-1 | 2026-07-29 06:15:28.892 UTC [49] DETAIL: Parameters: $1 = '100'
postgres-1 | 2026-07-29 06:15:28.893 UTC [49] LOG: execute S_1: COMMIT
postgres-1 | 2026-07-29 06:15:28.956 UTC [48] LOG: statement:
postgres-1 | 2026-07-29 06:15:28.956 UTC [48] LOG: statement: BEGIN
postgres-1 | 2026-07-29 06:15:28.958 UTC [48] LOG: execute S_2: with
postgres-1 | cte_poll_req as (
postgres-1 | select *
postgres-1 | from unnest($1, $2)
postgres-1 | as t(activity_name, lock_timeout)
postgres-1 | ),
postgres-1 | cte_poll as (
postgres-1 | select dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | from dex_activity_task as dat
postgres-1 | inner join dex_activity_task_queue as queue
postgres-1 | on queue.name = dat.queue_name
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = dat.activity_name
postgres-1 | where dat.queue_name = $3
postgres-1 | and queue.status = 'ACTIVE'
postgres-1 | and dat.status = 'QUEUED'
postgres-1 | and (dat.locked_until is null or dat.locked_until <= now())
postgres-1 | order by dat.priority desc
postgres-1 | , dat.created_at
postgres-1 | for no key update of dat skip locked
postgres-1 | limit $4
postgres-1 | )
postgres-1 | update dex_activity_task as dat
postgres-1 | set locked_by = $5
postgres-1 | , locked_until = now() + cte_poll_req.lock_timeout
postgres-1 | , lock_version = lock_version + 1
postgres-1 | , updated_at = now()
postgres-1 | from cte_poll
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = cte_poll.activity_name
postgres-1 | where dat.queue_name = $6
postgres-1 | and dat.workflow_run_id = cte_poll.workflow_run_id
postgres-1 | and dat.created_event_id = cte_poll.created_event_id
postgres-1 | returning dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | , dat.queue_name
postgres-1 | , dat.priority
postgres-1 | , dat.argument
postgres-1 | , dat.retry_policy
postgres-1 | , dat.attempt
postgres-1 | , dat.locked_until
postgres-1 | , dat.lock_version
postgres-1 |
postgres-1 | 2026-07-29 06:15:28.958 UTC [48] DETAIL: Parameters: $1 = '{import-bom,delete-files,invoke-vuln-analyzer,refresh-global-portfolio-metrics,process-scheduled-notification-rule,update-project-metrics,identify-internal-components,fetch-projects-for-metrics-update,fetch-package-metadata-resolution-candidates,publish-notification,import-vex,mirror-vuln-data-source,prepare-vuln-analysis,reconcile-vuln-analysis-results,resolve-purl-metadata,sync-vuln-policy-bundle,eval-project-policies,refresh-vulnerability-metrics}', $2 = '{00:05:00,00:01:00,00:05:00,00:05:00,00:05:00,00:05:00,00:30:00,00:01:00,00:01:00,00:01:00,00:05:00,00:15:00,00:05:00,00:05:00,00:10:00,00:05:00,00:05:00,00:05:00}', $3 = 'policy-evaluations', $4 = '5', $5 = 'b0a114985503-ef800c59', $6 = 'policy-evaluations'
postgres-1 | 2026-07-29 06:15:28.963 UTC [48] LOG: execute S_1: COMMIT
postgres-1 | 2026-07-29 06:15:28.964 UTC [49] LOG: statement: BEGIN
postgres-1 | 2026-07-29 06:15:28.968 UTC [49] LOG: execute S_2: with
postgres-1 | cte_poll_req as (
postgres-1 | select *
postgres-1 | from unnest($1, $2)
postgres-1 | as t(activity_name, lock_timeout)
postgres-1 | ),
postgres-1 | cte_poll as (
postgres-1 | select dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | from dex_activity_task as dat
postgres-1 | inner join dex_activity_task_queue as queue
postgres-1 | on queue.name = dat.queue_name
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = dat.activity_name
postgres-1 | where dat.queue_name = $3
postgres-1 | and queue.status = 'ACTIVE'
postgres-1 | and dat.status = 'QUEUED'
postgres-1 | and (dat.locked_until is null or dat.locked_until <= now())
postgres-1 | order by dat.priority desc
postgres-1 | , dat.created_at
postgres-1 | for no key update of dat skip locked
postgres-1 | limit $4
postgres-1 | )
postgres-1 | update dex_activity_task as dat
postgres-1 | set locked_by = $5
postgres-1 | , locked_until = now() + cte_poll_req.lock_timeout
postgres-1 | , lock_version = lock_version + 1
postgres-1 | , updated_at = now()
postgres-1 | from cte_poll
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = cte_poll.activity_name
postgres-1 | where dat.queue_name = $6
postgres-1 | and dat.workflow_run_id = cte_poll.workflow_run_id
postgres-1 | and dat.created_event_id = cte_poll.created_event_id
postgres-1 | returning dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | , dat.queue_name
postgres-1 | , dat.priority
postgres-1 | , dat.argument
postgres-1 | , dat.retry_policy
postgres-1 | , dat.attempt
postgres-1 | , dat.locked_until
postgres-1 | , dat.lock_version
postgres-1 |
postgres-1 | 2026-07-29 06:15:28.968 UTC [49] DETAIL: Parameters: $1 = '{import-bom,delete-files,invoke-vuln-analyzer,refresh-global-portfolio-metrics,process-scheduled-notification-rule,update-project-metrics,identify-internal-components,fetch-projects-for-metrics-update,fetch-package-metadata-resolution-candidates,publish-notification,import-vex,mirror-vuln-data-source,prepare-vuln-analysis,reconcile-vuln-analysis-results,resolve-purl-metadata,sync-vuln-policy-bundle,eval-project-policies,refresh-vulnerability-metrics}', $2 = '{00:05:00,00:01:00,00:05:00,00:05:00,00:05:00,00:05:00,00:30:00,00:01:00,00:01:00,00:01:00,00:05:00,00:15:00,00:05:00,00:05:00,00:10:00,00:05:00,00:05:00,00:05:00}', $3 = 'default', $4 = '25', $5 = 'b0a114985503-ef800c59', $6 = 'default'
postgres-1 | 2026-07-29 06:15:28.970 UTC [49] LOG: execute S_1: COMMIT
postgres-1 | 2026-07-29 06:15:29.015 UTC [50] LOG: statement:
postgres-1 | 2026-07-29 06:15:29.016 UTC [50] LOG: statement: BEGIN
postgres-1 | 2026-07-29 06:15:29.017 UTC [50] LOG: execute S_2: with
postgres-1 | cte_poll_req as (
postgres-1 | select *
postgres-1 | from unnest($1, $2)
postgres-1 | as t(activity_name, lock_timeout)
postgres-1 | ),
postgres-1 | cte_poll as (
postgres-1 | select dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | from dex_activity_task as dat
postgres-1 | inner join dex_activity_task_queue as queue
postgres-1 | on queue.name = dat.queue_name
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = dat.activity_name
postgres-1 | where dat.queue_name = $3
postgres-1 | and queue.status = 'ACTIVE'
postgres-1 | and dat.status = 'QUEUED'
postgres-1 | and (dat.locked_until is null or dat.locked_until <= now())
postgres-1 | order by dat.priority desc
postgres-1 | , dat.created_at
postgres-1 | for no key update of dat skip locked
postgres-1 | limit $4
postgres-1 | )
postgres-1 | update dex_activity_task as dat
postgres-1 | set locked_by = $5
postgres-1 | , locked_until = now() + cte_poll_req.lock_timeout
postgres-1 | , lock_version = lock_version + 1
postgres-1 | , updated_at = now()
postgres-1 | from cte_poll
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = cte_poll.activity_name
postgres-1 | where dat.queue_name = $6
postgres-1 | and dat.workflow_run_id = cte_poll.workflow_run_id
postgres-1 | and dat.created_event_id = cte_poll.created_event_id
postgres-1 | returning dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | , dat.queue_name
postgres-1 | , dat.priority
postgres-1 | , dat.argument
postgres-1 | , dat.retry_policy
postgres-1 | , dat.attempt
postgres-1 | , dat.locked_until
postgres-1 | , dat.lock_version
postgres-1 |
postgres-1 | 2026-07-29 06:15:29.017 UTC [50] DETAIL: Parameters: $1 = '{import-bom,delete-files,invoke-vuln-analyzer,refresh-global-portfolio-metrics,process-scheduled-notification-rule,update-project-metrics,identify-internal-components,fetch-projects-for-metrics-update,fetch-package-metadata-resolution-candidates,publish-notification,import-vex,mirror-vuln-data-source,prepare-vuln-analysis,reconcile-vuln-analysis-results,resolve-purl-metadata,sync-vuln-policy-bundle,eval-project-policies,refresh-vulnerability-metrics}', $2 = '{00:05:00,00:01:00,00:05:00,00:05:00,00:05:00,00:05:00,00:30:00,00:01:00,00:01:00,00:01:00,00:05:00,00:15:00,00:05:00,00:05:00,00:10:00,00:05:00,00:05:00,00:05:00}', $3 = 'vuln-analysis-reconciliations', $4 = '5', $5 = 'b0a114985503-ef800c59', $6 = 'vuln-analysis-reconciliations'
postgres-1 | 2026-07-29 06:15:29.018 UTC [50] LOG: execute S_1: COMMIT
postgres-1 | 2026-07-29 06:15:29.021 UTC [48] LOG: statement:
postgres-1 | 2026-07-29 06:15:29.055 UTC [48] LOG: statement: BEGIN
postgres-1 | 2026-07-29 06:15:29.056 UTC [48] LOG: execute S_2: with
postgres-1 | cte_poll_req as (
postgres-1 | select *
postgres-1 | from unnest($1, $2)
postgres-1 | as t(activity_name, lock_timeout)
postgres-1 | ),
postgres-1 | cte_poll as (
postgres-1 | select dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | from dex_activity_task as dat
postgres-1 | inner join dex_activity_task_queue as queue
postgres-1 | on queue.name = dat.queue_name
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = dat.activity_name
postgres-1 | where dat.queue_name = $3
postgres-1 | and queue.status = 'ACTIVE'
postgres-1 | and dat.status = 'QUEUED'
postgres-1 | and (dat.locked_until is null or dat.locked_until <= now())
postgres-1 | order by dat.priority desc
postgres-1 | , dat.created_at
postgres-1 | for no key update of dat skip locked
postgres-1 | limit $4
postgres-1 | )
postgres-1 | update dex_activity_task as dat
postgres-1 | set locked_by = $5
postgres-1 | , locked_until = now() + cte_poll_req.lock_timeout
postgres-1 | , lock_version = lock_version + 1
postgres-1 | , updated_at = now()
postgres-1 | from cte_poll
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = cte_poll.activity_name
postgres-1 | where dat.queue_name = $6
postgres-1 | and dat.workflow_run_id = cte_poll.workflow_run_id
postgres-1 | and dat.created_event_id = cte_poll.created_event_id
postgres-1 | returning dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | , dat.queue_name
postgres-1 | , dat.priority
postgres-1 | , dat.argument
postgres-1 | , dat.retry_policy
postgres-1 | , dat.attempt
postgres-1 | , dat.locked_until
postgres-1 | , dat.lock_version
postgres-1 |
postgres-1 | 2026-07-29 06:15:29.056 UTC [48] DETAIL: Parameters: $1 = '{import-bom,delete-files,invoke-vuln-analyzer,refresh-global-portfolio-metrics,process-scheduled-notification-rule,update-project-metrics,identify-internal-components,fetch-projects-for-metrics-update,fetch-package-metadata-resolution-candidates,publish-notification,import-vex,mirror-vuln-data-source,prepare-vuln-analysis,reconcile-vuln-analysis-results,resolve-purl-metadata,sync-vuln-policy-bundle,eval-project-policies,refresh-vulnerability-metrics}', $2 = '{00:05:00,00:01:00,00:05:00,00:05:00,00:05:00,00:05:00,00:30:00,00:01:00,00:01:00,00:01:00,00:05:00,00:15:00,00:05:00,00:05:00,00:10:00,00:05:00,00:05:00,00:05:00}', $3 = 'vuln-analyses', $4 = '10', $5 = 'b0a114985503-ef800c59', $6 = 'vuln-analyses'
postgres-1 | 2026-07-29 06:15:29.059 UTC [48] LOG: execute S_1: COMMIT
postgres-1 | 2026-07-29 06:15:29.229 UTC [51] LOG: statement:
postgres-1 | 2026-07-29 06:15:29.230 UTC [51] LOG: statement: BEGIN
postgres-1 | 2026-07-29 06:15:29.231 UTC [51] LOG: execute S_5: with
postgres-1 | cte_poll_req as (
postgres-1 | select *
postgres-1 | from unnest($1, $2)
postgres-1 | as t(activity_name, lock_timeout)
postgres-1 | ),
postgres-1 | cte_poll as (
postgres-1 | select dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | from dex_activity_task as dat
postgres-1 | inner join dex_activity_task_queue as queue
postgres-1 | on queue.name = dat.queue_name
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = dat.activity_name
postgres-1 | where dat.queue_name = $3
postgres-1 | and queue.status = 'ACTIVE'
postgres-1 | and dat.status = 'QUEUED'
postgres-1 | and (dat.locked_until is null or dat.locked_until <= now())
postgres-1 | order by dat.priority desc
postgres-1 | , dat.created_at
postgres-1 | for no key update of dat skip locked
postgres-1 | limit $4
postgres-1 | )
postgres-1 | update dex_activity_task as dat
postgres-1 | set locked_by = $5
postgres-1 | , locked_until = now() + cte_poll_req.lock_timeout
postgres-1 | , lock_version = lock_version + 1
postgres-1 | , updated_at = now()
postgres-1 | from cte_poll
postgres-1 | inner join cte_poll_req
postgres-1 | on cte_poll_req.activity_name = cte_poll.activity_name
postgres-1 | where dat.queue_name = $6
postgres-1 | and dat.workflow_run_id = cte_poll.workflow_run_id
postgres-1 | and dat.created_event_id = cte_poll.created_event_id
postgres-1 | returning dat.workflow_run_id
postgres-1 | , dat.created_event_id
postgres-1 | , dat.activity_name
postgres-1 | , dat.queue_name
postgres-1 | , dat.priority
postgres-1 | , dat.argument
postgres-1 | , dat.retry_policy
postgres-1 | , dat.attempt
postgres-1 | , dat.locked_until
postgres-1 | , dat.lock_version
```
### Expected Behavior
Should go back to not have a high cpu load and space usage.
### Dependency-Track Version
5.x
### Browser
Mozilla Firefox
### Checklist
- [x] I have read and understand the [contributing guidelines](https://github.com/DependencyTrack/dependency-track/blob/main/CONTRIBUTING.md#filing-issues)
- [x] I have checked the [existing issues](https://github.com/DependencyTrack/dependency-track/issues) for whether this defect was already reported
Contributor guide
Research direction
Start with the PostgreSQL query log in the report, especially the repeated NOTIFICATION_OUTBOX and dex_activity_task polling queries, and compare them with the v4-to-v5 migration history. Reproduce the sustained CPU and disk growth in the Docker deployment; done means identifying the responsible workload and documenting or fixing the condition that causes it to persist.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, postgresql
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100