1.4 KiB
1.4 KiB
ADR-0002: Use float sort_order for drag-and-drop ordering
Status
accepted
Context
The planning screens (PBI list, Story list, Task list, Solo board) all support drag-and-drop reordering. With integer positions, inserting an item between positions 3 and 4 requires renumbering every subsequent row — an O(N) write for every drag operation. At the scale of a sprint board this is tolerable, but it causes unnecessary lock contention and makes optimistic UI rollback harder. See docs/patterns/sort-order.md for the full implementation pattern.
Decision
Every ordered collection uses a Float column named sort_order. Inserting between two items sets sort_order = (prev + next) / 2. New items appended to the end get last + 1.0.
Consequences
Positive
- Reorder writes are O(1) — only the moved item's row is updated.
- Optimistic UI updates map directly to the same midpoint calculation.
- No lock contention on adjacent rows during concurrent drags.
Negative
- Repeated insertions between the same two items cause float precision drift. Mitigation: a periodic compaction job normalizes
sort_ordervalues to integers × 1000 when the gap drops below0.001. This is a known trade-off; compaction has not been needed in practice yet. - Queries that return items in
sort_orderorder must always includeORDER BY sort_order— there is no implicit ordering.