Skip to content

Title: PostgreSQL performance warning: 948,750 dead tuples after upgrading to Nextcloud 35.0.2 (AIO 15.0.2 Beta) #1266

Open

Description

@vawaver

Bug description

After successfully upgrading my Nextcloud AIO installation to 15.0.2 Beta, which includes Nextcloud Hub 26 Summer (35.0.2), I noticed a PostgreSQL performance warning in the system administration interface.

The upgrade itself completed successfully, and Nextcloud is running normally.

However, under Administration settings → System → Database → Performance, the following check is marked as failing:

Dead tuples in user tables

Warning · pg.dead_tuples

At least one user table has accumulated many dead tuples
— autovacuum may not be keeping up.

Largest table has 948750 dead tuples.

Tune autovacuum_naptime / autovacuum_vacuum_scale_factor,
or run VACUUM ANALYZE on the worst tables.

The interface also provides the following configuration snippet:

# postgresql.conf
autovacuum_naptime = 30

Since PostgreSQL is managed by Nextcloud AIO, I am unsure whether this setting should be modified manually or whether the warning indicates an issue with the database health check or its recommendations.

The displayed snippet also does not indicate the current value of autovacuum_naptime.

Steps to reproduce

  1. Run Nextcloud AIO 15.0.2 Beta with Nextcloud 35.0.2.
  2. Open Administration settings → System.
  3. Navigate to the database performance section.
  4. Observe the failing pg.dead_tuples check.
  5. Click Show config snippet to display the recommended PostgreSQL configuration.

Expected behavior

The database performance check should accurately reflect the database state and provide actionable recommendations appropriate for a managed PostgreSQL environment such as Nextcloud AIO.

Actual behavior

The check reports 948,750 dead tuples and recommends adjusting PostgreSQL autovacuum parameters or running VACUUM ANALYZE.

It is unclear whether this represents an actual database maintenance problem requiring intervention or whether the check or its recommendation needs adjustment.

Environment

  • Nextcloud: 35.0.2 – Hub 26 Summer
  • Nextcloud AIO: 15.0.2 Beta
  • Deployment: Docker / Nextcloud AIO
  • Host OS: Ubuntu 24.04 LTS (VM)
  • Database: PostgreSQL (AIO-managed container)
  • Affected check: pg.dead_tuples
  • Reported value: 948,750 dead tuples
  • Suggested configuration: autovacuum_naptime = 30

Additional context

I was referred to the Serverinfo repository by the Nextcloud AIO maintainer.

I also found a potentially related report, [nextcloud/serverinfo#1219](#1219), which mentions the same suggested autovacuum_naptime = 30 setting.

I would appreciate some guidance on whether this warning requires action in an AIO-managed PostgreSQL installation and, if so, what the appropriate approach would be.

Screenshots of the performance warning and the suggested configuration snippet are attached.

Image Image

Activity

  1. kesselb commented on Nov 9, 2026

    @kesselb
    Collaborator

    Thanks for the detailed report, and for checking with the AIO maintainers first!

    The check is likely too strict here. It fires as soon as any table has more than 100,000 dead tuples, regardless of table size. PostgreSQL's autovacuum only starts on a table once about 20% of its rows are dead, so on a large table like oc_filecache this number can be normal. No action is needed on your side, and please don't change the database settings of the AIO container by hand.

    @vawaver, to confirm, could you share the output of this query?

    SELECT relname, n_live_tup, n_dead_tup, last_autovacuum
    FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 5;

    We'll change the check to compare dead tuples with the size of the table instead of using a fixed number.

  2. kesselb commented on Nov 9, 2026

    @kesselb
    Collaborator

    Proposal for reworking pg.dead_tuples:

    PostgreSQL's autovacuum removes dead tuples on its own, so a high count is not a problem by itself. It only becomes one when autovacuum should have run but hasn't, for example because it is disabled or blocked by a long-open transaction.

    • In lib/Database/DatabaseProbe.php, replace MAX(n_dead_tup) with the number of tables whose dead tuples exceed autovacuum's own trigger point: n_dead_tup > autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * n_live_tup (defaults: 50 and 0.2, both available in pg_settings). Keep the table names for the details, like tables_without_index_use does.
    • In lib/Database/RuleSet/Postgres.php, update the rule to fire when that count is above 0, and change the recommendation: check that autovacuum is enabled and look for long-running or idle-in-transaction sessions, instead of suggesting autovacuum_naptime.
    • Add a unit test for both.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions