concurrent-editing

1 posts

figma

Realtime Editing of Ordered Sequences | Figma Blog (opens in new tab)

Figma needed a way for multiple users to edit ordered object sequences simultaneously while ensuring every client eventually reached the same state. Although Operational Transformation (OT) could solve the problem, Figma chose fractional indexing because it is simpler, supports efficient reordering, and was sufficient for design documents. The trade-offs—such as possible interleaving and growing index lengths—were acceptable in Figma’s use case. ## The Realtime Ordering Problem - Figma documents contain ordered children inside groups, components, and other compound objects. - Users can insert, delete, or reorder objects while edits are applied locally and propagated asynchronously. - Because clients may receive operations in different orders, the system must guarantee eventual consistency: every client must end up with the same document. ## Operational Transformation - OT transforms concurrent operations so they preserve the intended result regardless of application order. - For example, an insertion before a deletion may require adjusting the deletion’s index so it still removes the intended characters. - OT offers: - Strong performance and low memory usage for very large sequences. - Linearized concurrent insertions rather than interleaved content. - However: - It is difficult to understand and implement correctly. - Reordering is typically represented as a delete followed by an insert. - Supporting more operation types increases implementation complexity substantially because operations must be transformed against one another. - Figma considered OT excessive because its sequences were not enormous, interleaving was acceptable, and reordering was especially common. ## Fractional Indexing - Each object receives a numeric position, and children are ordered by sorting these positions. - To insert between two objects, Figma assigns the new object the average of their positions. - Positions are arbitrary-precision fractions between 0 and 1, stored as strings to preserve precision. - Figma uses a compact base-95 representation, omitting the leading `0.` and using the full ASCII range. - Reordering requires changing only one position value. ## Trade-offs and Conflict Handling - Fractional indexes are easy to understand and implement, but: - Index strings can grow after many insertions. - Concurrent insertions may interleave. - Averaging fails if two neighboring objects have identical indexes. - Index growth is not a practical concern for Figma because document sizes and user-driven reorder operations are limited. - Interleaving is generally acceptable for design objects, which often do not overlap; users can manually correct unusual ordering. - If two clients insert between the same objects, the server assigns a unique position to prevent duplicate indexes. Figma’s experience suggests that a simpler, stable algorithm can be more valuable than a theoretically stronger one. Fractional indexing made collaborative ordering easier to maintain and extend while meeting the practical needs of a design tool.