Skip to content

Index processing_status by project and by chunk - #1012

Merged
spashii merged 1 commit into
mainfrom
fix/processing-status-indexes
Aug 25, 2026
Merged

Index processing_status by project and by chunk#1012
spashii merged 1 commit into
mainfrom
fix/processing-status-indexes

Conversation

@spashii

@spashii spashii commented Aug 25, 2026

Copy link
Copy Markdown
Member

processing_status is an event log (about three million rows in production) keyed by conversation. Directus resolves it as a relation whenever a project or a conversation chunk is read, and neither project_id nor conversation_chunk_id had an index, so every such read scanned the whole table. Under load that put Directus's Postgres response time in the seconds and queued every dashboard request behind it.

This sets is_indexed on both fields the Directus way: flagged through the Directus API on a local instance, then sync.sh pull, so the snapshot matches what the environments carry and a future push never drops the indexes.

Deployment note. Directus only recognises an index as is_indexed when it is a single-column btree named <table>_<column>_index, and it reads that through its system cache. Both environments were indexed by hand during the incident, so before pushing this snapshot to an environment:

  1. Make sure the two indexes exist in exactly that shape: create index concurrently processing_status_project_id_index on processing_status (project_id) and the same for conversation_chunk_id. Build under a temporary name and rename if a differently shaped index already holds the name.
  2. POST /utils/cache/clear?system=true on that Directus, then confirm GET /fields/processing_status/project_id reports is_indexed: true.
  3. Then sync.sh diff shows nothing for these fields and the push is a no-op.

Both environments are already in that state: echo-next and production carry the two single-column indexes, their system caches were cleared, both report is_indexed: true, and a read-only sync.sh diff against production lists no change on processing_status. The push of this snapshot is a no-op for these two fields.

Follow-ups, separate: stop resolving processing_status on project and chunk reads (the relation returns nothing useful), and stop the summariser writing a failure row per attempt.

processing_status is an event log of three million rows keyed by
conversation. Directus resolves it as a relation on every project and
every chunk read, and neither column had an index, so each read was a
sequential scan of the whole table. Set is_indexed on project_id and
conversation_chunk_id through the Directus API on a local instance and
pulled the snapshot, so a schema push creates the same indexes with the
names Directus expects.
@spashii
spashii merged commit cd8a3ba into main Aug 25, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant