Core Entities
Document: (doc_id, title, owner_id, workspace_id, current_version_id, status=ACTIVE|ARCHIVED|DELETED, created_at, updated_at). DocumentVersion: (version_id, doc_id, version_number, content_url, content_hash, size_bytes, created_by, created_at, change_summary). DocumentPermission: (perm_id, doc_id, principal_type=USER|GROUP|WORKSPACE, principal_id, permission=VIEWER|COMMENTER|EDITOR|OWNER). DocumentComment: (comment_id, doc_id, version_id, anchor_text, body, author_id, resolved_at, thread_id). DocumentTag: many-to-many. ShareLink: (link_id, doc_id, token, permission, expires_at, is_active).
Versioning and Storage
Each save creates a new DocumentVersion. Content is stored in S3 as immutable objects (keyed by content_hash for deduplication). If two users save identical content: both version records point to the same S3 object. Version numbering: sequential integers (1, 2, 3…) per document. The Document table points to current_version_id for fast access. Version history: list all versions ordered by version_number desc. Restore: set current_version_id to the target version. Delta storage: for large documents, storing full content per version is expensive. Instead, store a diff (unified diff format) from the previous version and reconstruct by applying diffs. Delta storage reduces storage cost by 80-90% for text documents. Binary files (PDFs, images) always store the full file per version (diffs are not effective).
Permission Model
Hierarchical permissions: workspace-level defaults -> folder-level -> document-level. A user’s effective permission = max(workspace_default, folder_perm, doc_perm) where OWNER > EDITOR > COMMENTER > VIEWER. Inheritance: if a document has no explicit permission entry for a user, they inherit from the folder, then the workspace. Permission checks: on every document access, resolve the user’s effective permission. Cache the resolved permission in Redis (key: user_id:doc_id, TTL: 5 minutes). Invalidate on permission change. Group permissions: a user can be in multiple groups. Their permission is the maximum across all applicable group permissions plus any individual permissions. Share links: bypass the regular permission check; verify the token, check token’s permission level and expiry. Link tokens are cryptographically random (128-bit).
Full-text Search
Index document content in Elasticsearch. Index: doc_id, title, content (extracted text), tags, owner_id, workspace_id, created_at, permission_acl. Permission-filtered search: include the user’s accessible doc_ids as a filter (ACL filtering). For large workspaces with thousands of documents: pre-compute accessible document IDs per user on permission change (stored in Redis). At search time: intersect search results with accessible set. Content extraction: PDF and DOCX files require text extraction before indexing (Apache Tika, AWS Textract). Re-index when a new version is created. Incremental indexing via Kafka: on DocumentVersion creation, publish an event. An indexing worker consumes the event and updates Elasticsearch.
Real-time Collaboration
Multiple users editing the same document simultaneously. Challenges: conflict resolution, cursor positions, operational transforms. Approach: Operational Transformation (OT) — the algorithm underlying Google Docs. Each edit is an operation (insert char at position, delete char at position). Operations from concurrent editors are transformed against each other to maintain consistency. Alternative: CRDTs (Conflict-free Replicated Data Types) — a newer approach used by Figma and some editors. Each character has a unique ID; concurrent inserts are ordered deterministically. Implementation: use a real-time collaboration library (ShareDB for OT, Yjs for CRDT). WebSocket connection per document: server broadcasts operations to all connected editors. For simpler collaboration: last-write-wins with conflict detection (detect conflicts using version numbers, prompt user to resolve).
Interview Tips
- Versioning: the key design choice is full-content vs delta storage. Full-content is simpler and enables O(1) version access. Delta is cheaper but requires diff application on access.
- Permission resolution is complex with inheritance and groups. Always clarify: is inheritance additive (combine all permissions) or override (most specific wins)? For most document systems: most specific wins, with a maximum operation.
- For real-time collaboration, OT is the established standard (Google Docs). CRDTs are newer and simpler to reason about. In an interview, mentioning the existence of both and the trade-offs is sufficient.
Asked at: Atlassian Interview Guide
Asked at: LinkedIn Interview Guide
Asked at: Snap Interview Guide
Asked at: Shopify Interview Guide