#13585·outline

Deleting a large document subtree still issues one update per descendant

Author: 47starCreated Aug 29, 2026Updated Aug 30, 2026
Labelsbugperformance

Is there an existing issue for this?

  • I have searched the existing issues

This is not related to configuring Outline

  • The issue is not related to self-hosting config

Current Behavior

Deleting a document also soft-deletes all of its descendants. When the document has a large subtree, the delete request may time out or return a gateway error before the operation completes.

The subtree is resolved in one recursive query, but the descendants are then loaded and destroyed one at a time. A subtree with N descendants therefore still performs N soft-delete updates within the request transaction.

If the request or database timeout is reached, the transaction is rolled back and the document remains undeleted.

Expected Behavior

Deleting a document with a large number of descendants should complete without exceeding the request timeout or issuing one update per descendant.

Steps To Reproduce

  1. Create or import a document with a large number of descendants.
  2. Delete the root document.
  3. Observe the duration and database queries for the delete request.
  4. With a sufficiently large subtree, the request times out or returns a gateway error.

Environment

  • Outline: current main
  • Database: PostgreSQL

Anything else?

#13311 reduced the subtree lookup to a recursive query, but intentionally kept individual destroy() calls so that model hooks run for each descendant.

This leaves the remaining soft-delete updates as the part that still scales with the number of descendants. Replacing them with a bulk update would address the query count, but would also skip instance-level destroy hooks. #13484 currently relies on one of those hooks to record deletedById.

The alternatives I can see are:

  • Bulk-update the descendants and explicitly preserve the required deletion fields.
  • Keep the existing destroy behavior but process descendants asynchronously in bounded batches.
  • Separate the bulk database update from retryable per-document side effects.

I’m opening this issue before preparing a change because the appropriate fix depends on which deletion lifecycle behavior needs to remain synchronous.