# System Design: Design Notion — Collaborative Workspace, Block System, Database Views, Real-Time Editing, API

Source: https://www.techinterview.org/post/3233474362/system-design-design-notion-collaborative-workspace-blocks-database-real-time-editing-permissions-api-integrations/
Updated: 2026-04-20 · techinterview.org

Notion is a collaborative workspace that combines documents, databases, wikis, and project management in a single tool. With 30+ million users, Notion unique block-based architecture and flexible database system create distinctive system design challenges. This guide covers the block data model, database engine, collaboration, and the API that makes Notion extensible.

## Block-Based Data Model

Everything in Notion is a block. A page is a block. A paragraph is a block. A heading, image, to-do item, embed, and database are all blocks. Blocks can contain other blocks (nesting). Data model: block: block_id (UUID), type (text, heading, image, database, page, toggle, callout, etc.), parent_id (the block this is nested under), properties (type-specific: text content, image URL, checkbox state), children (ordered list of child block_ids), created_by, created_at, last_edited_by, last_edited_at. The entire workspace is a tree of blocks. A page is a root block containing child blocks (paragraphs, headings, images). A database is a block whose children are database rows (each row is also a block/page). This recursive structure is powerful: a database cell can contain rich text with nested blocks, a toggle can contain a full document, and pages can be nested infinitely. Storage: blocks are stored in a database (PostgreSQL or similar) keyed by block_id. The parent-child relationship is stored as parent_id on each block. Retrieving a page: fetch the root block, then recursively fetch children. Optimization: batch-fetch children in a single query using IN clause or a recursive CTE.

## Notion Databases

A Notion database is a collection of pages (rows) with typed properties (columns). Property types: text, number, select (dropdown), multi-select, date, person, relation (link to another database), formula, rollup (aggregate from related records), and more. Each row is a full page -- clicking a row opens it as a page with rich content. Database views: the same data can be displayed as: table (spreadsheet-like), board (Kanban -- grouped by a select property), list, calendar (positioned by date property), gallery (visual cards), and timeline (Gantt chart by date range). Each view has its own: filter rules, sort order, visible properties, and group-by settings. All views share the same underlying data. Implementation: the database is stored as a collection of blocks (one per row) with structured properties. Each property value is stored as: (block_id, property_id, value, type). Queries: fetching a table view = SELECT * FROM properties WHERE database_id = X, apply filters, sort, and paginate. Filters: the filter engine supports compound conditions: (property A = "In Progress" AND property B > 100) OR property C contains "urgent." Implemented as a predicate tree evaluated against each row. For large databases (10,000+ rows): index commonly filtered properties. Notion uses a custom query engine optimized for the block-property model.

## Real-Time Collaboration

Notion supports real-time collaborative editing similar to Google Docs. Multiple users can edit the same page simultaneously. Architecture: CRDT-inspired conflict resolution at the block level. Each block property change is an operation: set(block_id, property, value, timestamp, user_id). Last-writer-wins per property per block. If User A changes a paragraph text and User B changes the same paragraph simultaneously: the last timestamp wins. Unlike character-level CRDTs (Google Docs), Notion operates at the block level. Two users editing different blocks in the same page have no conflict. Two users editing the same block: last-writer-wins on the specific property. Text within a block: Notion uses a character-level CRDT for rich text content within a single text block. This allows two users to type in the same paragraph without overwriting each other. Structural operations: adding, removing, and reordering blocks. These are tree operations (insert child, remove child, move child). Notion uses a tree CRDT that handles concurrent structural edits: if User A adds a block after block X and User B deletes block X simultaneously, A block is orphaned and reparented to X parent. WebSocket: all editors of a page maintain WebSocket connections to the collaboration service. Operations are broadcast in real-time. Presence: cursor positions and active blocks are shared among editors.

## Permissions and Sharing

Notion has a hierarchical permission model: permissions are set on pages/databases and inherited by all child blocks. Permission levels: full access, can edit, can comment, can view. Sharing targets: specific users, groups, the entire workspace, or anyone with a link (public). Inheritance: a page nested inside a shared page inherits the parent permissions. Explicit permissions on a child page override inherited ones. "Lock page" prevents edits by non-owners (useful for templates and documentation that should not be accidentally modified). Guest access: external users (outside the workspace) can be invited to specific pages. They see only the shared content, not the broader workspace. Workspace structure: personal pages (visible only to the owner), shared pages (visible to invited users), and teamspaces (visible to all workspace members). The permission check on every block access: (1) Check if the block page has explicit permissions for the user. (2) If not, walk up the parent chain until finding a page with permissions. (3) Apply the most specific permission found. Caching: resolve and cache the effective permission per user per page in Redis. Invalidate when permissions change on any ancestor page.

## API and Integrations

The Notion API enables programmatic access to workspace content. Core endpoints: (1) Pages -- create, read, update pages. A page is a block with child blocks. (2) Databases -- query databases with filters, sorts, and pagination. Create/update database rows (pages with properties). (3) Blocks -- CRUD on individual blocks. Append children to a page. (4) Search -- full-text search across the workspace. (5) Users -- list workspace members. Authentication: OAuth 2.0 for third-party integrations. Internal integrations use a secret token scoped to a workspace. Rate limits: 3 requests per second per integration (conservative to protect the platform). Pagination: cursor-based for all list endpoints. Use cases: (1) Sync external data into Notion databases (import Jira tickets, GitHub issues). (2) Automate workflows (when a database row status changes to "Done," update a project tracker). (3) Build custom views (render Notion database data in a custom dashboard). (4) Content publishing (export Notion pages as blog posts). Webhooks (limited): Notion does not yet have full webhook support. Integrations poll for changes using the search endpoint with a filter on last_edited_time. This is less efficient than event-driven webhooks but functional for most use cases.
