Analytics tables grow significantly after successful analytics run and later shrink — clarification needed

Hi everyone,

I’m looking for some clarification on how DHIS2 Analytics handles the creation, replacement, and cleanup of analytics event tables.

We have disk storage constraints, so we normally run analytics only twice a week. Recently, I noticed an interesting pattern with our analytics_event_* tables.

After one analytics run completed successfully, I noticed that the following tables had grown significantly:

• analytics_event_klst0hiyslv_2025

• analytics_event_klst0hiyslv_2026

At that point, the tables were approximately 63 GB and 59 GB, respectively (Query 1 below).

However, after a few days, the same tables had dropped to approximately 23 MB each, and the overall database size was around 145 GB (Query 2).

Then, on Monday, 28 September 2026 at around 23:00, we ran analytics again. The analytics process completed successfully, but afterwards the same tables had grown again, this time to approximately 63 GB and 69 GB, while the database size had increased to approximately 299 GB (Query 3).

Query 1 — tables after an analytics run

sudo lxc exec postgres – sudo -u postgres psql -d xxxx -c "

SELECT

  • c.oid::regclass AS relation,*

  • c.relkind,*

  • c.relispartition,*

  • pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size*

FROM pg_class c

JOIN pg_namespace n ON n.oid = c.relnamespace

WHERE n.nspname = ‘public’

  • AND c.relname LIKE ‘analytics_%’*

ORDER BY pg_total_relation_size(c.oid) DESC;

"

                     relation                         | relkind | relispartition | total_size

----------------------------------------------------------±--------±---------------±-----------

analytics_event_klst0hiyslv_2025 | r | f | 63 GB

analytics_event_klst0hiyslv_2026 | r | f | 59 GB

Query 2 — several days later

sudo lxc exec postgres – sudo -u postgres psql -d xxxx -c "

SELECT

  • pg_size_pretty(pg_database_size(‘xxxx’)),*

  • pg_size_pretty(pg_total_relation_size(‘public.analytics_event_klst0hiyslv_2025’)),*

  • pg_size_pretty(pg_total_relation_size(‘public.analytics_event_klst0hiyslv_2026’));*

"

  • pg_size_pretty | pg_size_pretty | pg_size_pretty*

----------------±---------------±---------------

  • 145 GB | 23 MB | 23 MB*

Query 3 — after the analytics run on 28 September 2026

sudo lxc exec postgres – sudo -u postgres psql -d xxxx -c "

SELECT

  • pg_size_pretty(pg_database_size(‘xxxx’)),*

  • pg_size_pretty(pg_total_relation_size(‘public.analytics_event_klst0hiyslv_2025’)),*

  • pg_size_pretty(pg_total_relation_size(‘public.analytics_event_klst0hiyslv_2026’));*

"

  • pg_size_pretty | pg_size_pretty | pg_size_pretty*

----------------±---------------±---------------

  • 299 GB | 63 GB | 69 GB*

(1 row)

Questions

Could someone help me understand what is happening here?

1. Is this expected behavior during/after an Analytics Tables generation process?

2. Are these large analytics_event_* tables temporary/intermediate tables that are later swapped, renamed, or replaced?

3. Could the delay between the analytics run completing and the old tables being cleaned up explain why the tables initially consume tens of GB and later drop to a few MB?

4. If so, what is the expected lifecycle and cleanup behavior, and how long should we normally expect these tables to remain at their larger size?

5. Given our disk-space constraints, what would be the recommended way to monitor analytics runs and estimate the temporary disk space required?

6. Is there a specific DHIS2 log, database query, or metric that can help determine whether the large tables are active analytics tables, temporary tables, or tables waiting to be swapped/cleaned up?

I’m particularly interested in understanding whether the increase from 145 GB to 299 GB is expected during the analytics process and how we can safely monitor this without risking the PostgreSQL server running out of disk space.

Any explanation of the underlying DHIS2 Analytics table-generation/swap process would be greatly appreciated.

Thanks

I’m clearly not understanding how you endup with so much variations.

my hypothesis would be

  • you perhaps have several cron launching analytics but with different settings (not that you can specify the number of years to relaunch on, which table is ignored,… )
  • someone is running them manually perhaps with less years ?
  • there’s also a “continuous” analytics job that create a special “_0” tables that take precedence on the others during query, with only the “new/modified data”.
  • some metadata influence greatly the size of the tables (think category combo for aggregates)
  • extra data element / orgunit groupsets has been added, the depth of the pyramid has been modified ?
  • 2 heavy columns can be the geometries especially if they were not “simplified” before upload
  • TEI/EVENTs can also be soft deleted, they can disappear from analytics

You should perhaps investigate if there are changes in the layout (columns) or row counts.
Analytics have separated log folder, you can perhaps investigate the “concurrent” run thing there.

My recommendation since you have a lot of data, migrate asap to latest dhis2, and switch clickhouse or apache loris for analytics, it’s day and night in term of performance. But I don’t have all the return of experience about diskusage (my guess is that it’s less storage). For machine CPU/Memory is clearly less for a better experience.

Tables will always “expands” the more data comes in… generally mainly the current year, but it really depends on what your user are doing around dhis2, perhaps importing past data.

If you keep postgres for analytics… in term of storage always plan for more… it’s clearly not “if” but “when” will I need more storage.