epam / epam/ai-dial-admin-evaluation-framework-backend

[eval] [tech-debt] Partition analytics tables to sustain query performance and enable retention by partition drop

Open
#33 0 comments 0 reactions 1 assignee Claimed by @vladyslavchuhai-spec View on GitHub
enhancement P3 - Medium
Dominant language
Java
Stars
3
Forks
1
Avg merge
1d 1h
Merged PRs (30d)
27

Description

### Name and Version

0.1.0

### What is the problem this feature will solve?

The analytics database holds the high-volume, append-only output of every evaluation run — test case run results, eval summaries, metric snapshots, and related artifacts. These tables grow monotonically with no archival mechanism in place, and two problems are emerging as a tech-debt signal rather than an outage:

1. **Query performance degradation as tables grow.** List, aggregation, and detail queries already rely on selective column projection and JSONB-aware indexing to stay responsive. As row counts grow into the tens or hundreds of millions, planner cost, index size, and TOAST overhead will progressively erode latency on the analytics read paths — particularly cursor-paginated list endpoints and metric aggregation queries.
2. **No efficient retention / archival path.** Today the only way to remove old data is row-level `DELETE`, which is expensive at volume, generates large amounts of WAL, fragments tables, and depends on autovacuum to reclaim space. There is no operational lever to enforce a retention window (e.g. "keep N months of run data") without an outsized cost.

This is a proactive sweep — addressing it now, before the tables become unwieldy, is significantly cheaper than retrofitting partitioning under production pressure.

### What is the feature you are proposing to solve the problem?

Introduce **native PostgreSQL declarative partitioning** on the high-volume analytics tables, with **time-based partitioning** as the preferred initial strategy (e.g. monthly partitions keyed on the existing creation timestamp).

High-level behavior:

- The analytics tables most affected by growth are converted to partitioned parents, with child partitions covering bounded time ranges.
- New rows route automatically to the appropriate partition based on the partition key; the write path on the application side is unchanged.
- Queries that already filter or order by the time/cursor key benefit from partition pruning, keeping per-query work bounded as the overall dataset grows.
- A retention policy is expressed as **dropping (or detaching) whole partitions** rather than row-level `DELETE`, making archival a near-instant metadata operation that does not bloat the table or generate large WAL volumes.
- Partition creation and pruning are managed operationally (scheduled job or maintenance task) rather than ad-hoc, so partitions for upcoming periods always exist before writes need them.
- Migration from the current non-partitioned tables is planned as an offline/maintenance-window activity with a documented rollback path; existing indexes, constraints, and foreign-key semantics are preserved on the partitioned layout.
- Scope is **analytics DB only**. The meta DB (suites, runs, configuration) is unaffected by this change.

No public REST API changes. No DTO contract changes. Cursor-based pagination semantics on analytics endpoints are preserved — partition pruning is transparent to clients.

The exact partition key, partition granularity (monthly vs. weekly), and retention window are intentionally left open and will be decided during the design phase based on current table sizes, ingestion rate, and operational preferences. Time-based is the preferred starting point; hash or composite strategies remain on the table if profiling shows the workload is not time-skewed.

### What alternatives have you considered?

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.