본문 바로가기
교양/과학기술

노션은 어떻게 2,000억 개의 노트를 관리하나? 데이터베이스 샤딩과 데이터 레이크 전략 파헤치기

by Agent 2025. 4. 6.

시간이 흐를수록 노트와 문서는 계속 쌓이고 있지만, 노션(Notion)은 어떻게 이 모든 데이터를 멈춤 없이 처리할까요? 2억 개를 넘어선 블록(block)들이 실시간으로 업데이트되는 환경에서도 시스템이 안정적으로 운영되는 비결이 있습니다. 오늘은 노션이 급격한 성장 속에서 어떻게 데이터베이스를 관리하고 확장했는지, 그 과정에서 어떤 기술적 선택을 했는지 살펴보겠습니다.

How Notion Handles 200 BILLION Notes (Without Crashing)
How Notion Handles 200 BILLION Notes (Without Crashing)

 

How Notion Handles 200 BILLION Notes (Without Crashing)

이 영상에서는 급성장한 노션이 어떻게 2,000억 개의 노트를 효율적으로 처리하고 시스템 다운을 방지할 수 있는지 설명합니다, **트래픽**을 분산시키고 있습니다. 또한, **데이터 레이크**를 구

lilys.ai

 

📊 노션의 데이터 구조와 폭발적 성장

노션은 단순한 메모장이 아닙니다. 겉으로는 심플한 문서 편집기처럼 보이지만, 내부적으로는 실시간 협업 데이터베이스가 작동하고 있습니다. 노션에서 우리가 작성하는 모든 텍스트, 체크박스, 이미지, 테이블은 모두 '블록'이라는 단위로 관리됩니다.

블록의 기본 구조는 다음과 같습니다:

CREATE TABLE blocks (
  id UUID PRIMARY KEY,
  type VARCHAR(50), -- 'paragraph', 'checkbox' 등
  parent_id UUID, -- 부모 블록 (중첩 구조)
  workspace_id UUID, -- 샤딩 기준점
  properties JSONB -- 유연한 콘텐츠 저장
);

재미있는 사실은, 노션에서 ↑ 또는 ↓ 키로 이동할 때 커서가 움직이는 것처럼 보이지만, 실제로는 데이터베이스 행 사이를 이동하는 것입니다. 10개 요소가 있는 단순한 페이지도 내부적으로는 10개 이상의 데이터베이스 쿼리가 발생하는 것이죠!

2020년 중반, 노션은 5년 동안 1만 배의 성장을 경험했습니다. 2024년 현재는 1억 명 이상의 사용자가 노션을 사용하고 있으며, 그들이 생성한 블록은 2,000억 개를 넘어섰습니다. 이런 규모에서 단일 데이터베이스로는 감당하기 어려워졌고, 데이터베이스 CPU가 과부하되어 엔지니어들이 밤에 알람을 받는 일이 잦아졌습니다.

🔄 샤딩의 필요성과 구현 방법

샤딩이 필요한 순간

샤딩(Sharding)은 데이터베이스를 여러 개의 작은 조각으로 나누는 기술입니다. 많은 기술 블로그에서는 "너무 일찍 샤딩하지 말라"고 조언하지만, 노션의 규모에서는 이미 선택이 아닌 필수가 되었습니다.

결정적 계기는 PostgreSQL의 VACUUM 프로세스가 지속적으로 멈추기 시작했을 때였습니다. 이로 인해 데이터베이스는 사용하지 않는 튜플(tuple)로부터 디스크 공간을 회수하지 못했고, 더 심각한 문제는 TXID wraparound라는 시한폭탄이 카운트다운에 들어갔다는 것입니다. 이 상태가 계속되면 데이터베이스가 완전히 멈출 수 있는 위험이 있었습니다.

샤딩 전략 설계

노션은 워크스페이스 ID를 기준으로 데이터를 샤딩하기로 결정했습니다. 이는 사용자들이 대부분 자신의 워크스페이스 내에서 작업하기 때문에 논리적인 선택이었습니다.

이를 위해 노션은 원래의 대형 PostgreSQL 데이터베이스를 32개의 개별 인스턴스로 나누고, 각 인스턴스에 15개의 논리적 샤드를 할당하여 총 480개의 샤드를 생성했습니다. 이제 애플리케이션은 간단한 해시 함수를 사용해 요청을 올바른 샤드로 라우팅합니다:

shard = hash(workspace_id) % 480 # 단순하지만 효과적인 방식

5분 다운타임으로 마이그레이션 성공하기

노션은 200억 개 이상의 블록을 5분이라는 짧은 다운타임으로 마이그레이션하는 대담한 작전을 세웠습니다. 이를 위한 접근법은 다음과 같았습니다:

  1. 이중 쓰기(Double Write) 구현:
def save_block(block):
  old_db.write(block) # 기존 데이터베이스
  new_sharded_db.write(block) # 새 샤딩 데이터베이스
  1. 감사 로그(Audit Log): Kafka 스트림을 통해 모든 변경사항을 기록하여 데이터 일관성을 확인
  2. 백필링(Backfilling): 96개의 CPU를 가진 강력한 머신을 이용해 3일 동안 전체 데이터베이스 복사
  3. 전환(Cutover): 실제 전환은 놀랍게도 5분 만에 완료되었습니다!

🌊 데이터 레이크 구축과 처리 시스템

샤딩된 데이터베이스는 실시간 사용자 요청을 처리하는 데 유용했지만, 분석 및 머신러닝과 같은 무거운 작업에는 별도의 솔루션이 필요했습니다.

데이터 레이크의 필요성

노션의 블록 데이터는 6~12개월마다 2배씩 증가하고 있었습니다. 처음에는 Fivetran을 사용하여 Postgres WAL에서 Snowflake로 데이터를 수집하는 간단한 ELT 파이프라인으로 시작했습니다. 그러나 이 접근법은 두 가지 큰 문제에 직면했습니다:

  1. 운영 복잡성: 480개의 Fivetran 커넥터를 관리하는 오버헤드가 너무 컸습니다.
  2. 비용 증가: 노션의 업데이트 중심 워크로드는 Snowflake에서 처리하기에 비효율적이었습니다.

인하우스 데이터 레이크 구축

노션은 자체 데이터 레이크를 구축하기로 결정하고 다음과 같은 목표를 설정했습니다:

  1. 원시 데이터와 처리된 데이터를 대규모로 저장할 수 있는 저장소 구축
  2. 모든 워크로드에 대해 빠르고, 확장 가능하며, 관리 가능하고, 비용 효율적인 데이터 수집 및 계산 지원
  3. AI, 검색 및 기타 제품 요구 사항 지원

데이터 파이프라인 설계

노션의 데이터 레이크 파이프라인은 다음과 같이 설계되었습니다:

  1. 수집(Ingestion): Debezium CDC 커넥터를 사용하여 Postgres에서 Kafka로 증분 업데이트된 데이터를 수집
  2. 저장(Storage): Apache Hudi를 사용하여 이러한 업데이트를 Kafka에서 Amazon S3로 저장
  3. 처리(Processing): Apache Spark를 사용하여 변환, 비정규화 및 보강 작업 수행
  4. 서빙(Serving): 처리된 데이터를 다시 S3에 저장하거나 다운스트림 시스템에 전달

이 아키텍처의 핵심은 오픈 소스 도구를 적극 활용하여 비용을 절감하면서도 확장성과 성능을 확보한 것입니다. Apache Spark는 대규모 데이터셋을 효율적으로 처리할 수 있고, Apache Kafka는 안정적인 메시징 시스템을 제공합니다.

⚡ 두 번째 확장: 샤딩 최적화

첫 번째 샤딩이 성공적이었지만, 노션의 성장은 계속되었고 새로운 문제에 직면했습니다.

샤드 용량 한계 도달

샤드의 활용률이 90%에 도달하자 시스템은 다시 불안정해지기 시작했습니다. 노션은 다음과 같은 조치를 취했습니다:

  1. 32대의 데이터베이스 머신을 96대로 증가
  2. 머신당 샤드 수를 15개에서 5개로 감소
  3. Postgres의 논리적 복제를 사용하여 데이터를 새 시스템으로 복사
  4. Pgbouncer를 통해 트래픽을 효율적으로 분배

하지만 이 접근법은 Pgbouncer의 연결 한계에 도달하는 새로운 문제를 야기했습니다.

연결 관리 개선

최종 솔루션으로 노션은 샤드를 5개의 논리적 그룹으로 나누어 24개의 데이터베이스를 관리하는 방식을 채택했습니다. 이를 통해:

  1. 연결 한계를 방지하고 문제를 더 쉽게 분리할 수 있었습니다.
  2. "어두운 읽기(dark reads)"를 통해 두 데이터베이스 간의 일관성을 테스트했습니다.
  3. 사용자에게 다운타임 없이 점진적으로 전환할 수 있었습니다.

🔍 노션의 데이터 관리에서 배울 수 있는 교훈

노션의 사례를 통해 우리는 다음과 같은 교훈을 얻을 수 있습니다:

  1. 샤딩 시기 결정하기: 너무 일찍 샤딩하면 복잡성만 증가시키고, 너무 늦으면 시스템 안정성이 위협받습니다. 노션은 VACUUM 프로세스 실패와 TXID wraparound 위험이라는 명확한 신호를 기다렸습니다.
  2. 워크로드 특성 이해하기: 노션의 업데이트 중심 워크로드는 Snowflake와 같은 기존 데이터 웨어하우스에 적합하지 않았습니다. 자신의 워크로드 특성을 이해하고 그에 맞는 솔루션을 선택하는 것이 중요합니다.
  3. 오픈 소스 활용하기: 노션은 Apache Spark, Apache Kafka, Apache Hudi와 같은 오픈 소스 도구를 적극 활용하여 비용을 절감하면서도 확장성과 성능을 확보했습니다.
  4. 점진적 전환 전략: 5분이라는 짧은 다운타임으로 200억 개의 블록을 마이그레이션한 노션의 접근법은 "빅뱅" 방식보다 안전하고 효율적입니다.

노션의 사례는 빠르게 성장하는 스타트업이 데이터베이스 확장 문제를 어떻게 해결할 수 있는지 보여주는 좋은 예입니다. 샤딩, 데이터 레이크 구축, 오픈 소스 활용 등의 전략은 다른 기업들에게도 유용한 참고 자료가 될 것입니다.

마치며

노션은 기술적 도전에 적극적으로 대응하여 1억 명 이상의 사용자와 2,000억 개 이상의 블록을 안정적으로 지원하는 플랫폼으로 성장했습니다. 이 과정에서 적용한 데이터베이스 샤딩, 데이터 레이크 구축, 오픈 소스 활용 등의 전략은 빠르게 성장하는 모든 기술 기업에게 귀중한 교훈을 제공합니다.

여러분의 프로젝트에서도 이런 대규모 데이터 관리 기술을 고려해 보시는 것은 어떨까요? 노션처럼 여러분의 서비스도 폭발적인 성장을 경험하게 될지도 모릅니다!


#노션 #데이터베이스샤딩 #PostgreSQL #데이터레이크 #ApacheSpark #ApacheKafka #데이터엔지니어링 #대규모데이터처리 #시스템확장성 #오픈소스


How Notion Manages 200 Billion Notes: Database Sharding and Data Lake Strategies Revealed

As notes and documents continue to accumulate over time, how does Notion handle all this data without interruptions? There's a secret to how systems remain stable even in environments where over 200 billion blocks are updated in real-time. Today, we'll examine how Notion has managed and scaled its databases during rapid growth, and what technical choices they made in the process.

📊 Notion's Data Structure and Explosive Growth

Notion is not just a simple notepad. While it appears to be a simple document editor on the surface, internally, a real-time collaborative database is functioning. Everything we create in Notion—text, checkboxes, images, tables—is managed in units called 'blocks'.

The basic structure of a block is as follows:

CREATE TABLE blocks (
  id UUID PRIMARY KEY,
  type VARCHAR(50), -- 'paragraph', 'checkbox', etc.
  parent_id UUID, -- Parent block (nested structure)
  workspace_id UUID, -- Sharding basis
  properties JSONB -- Flexible content storage
);

An interesting fact is that when you move using the ↑ or ↓ keys in Notion, it looks like the cursor is moving, but you're actually moving between database rows. Even a simple page with 10 elements internally generates more than 10 database queries!

By mid-2020, Notion had experienced 10,000-fold growth over five years. As of 2024, over 100 million users are using Notion, and they've created over 200 billion blocks. At this scale, a single database became insufficient, causing database CPU overloads and frequent night alarms for engineers.

🔄 The Need for Sharding and Implementation Method

When Sharding Becomes Necessary

Sharding is a technique for dividing a database into multiple smaller pieces. Many tech blogs advise "don't shard too early," but at Notion's scale, it had already become a necessity rather than a choice.

The decisive moment came when PostgreSQL's VACUUM process began consistently stopping. This prevented the database from reclaiming disk space from unused tuples, and more seriously, a time bomb called TXID wraparound began counting down. If this state continued, there was a risk that the database could completely stop.

Designing a Sharding Strategy

Notion decided to shard data based on workspace ID. This was a logical choice because users mostly work within their own workspaces.

To implement this, Notion divided its original large PostgreSQL database into 32 separate instances, assigning 15 logical shards to each instance, creating a total of 480 shards. Now the application uses a simple hash function to route requests to the correct shard:

shard = hash(workspace_id) % 480 # Simple but effective approach

Successful Migration with 5 Minutes of Downtime

Notion set up a bold operation to migrate over 20 billion blocks with just 5 minutes of downtime. Their approach was as follows:

  1. Implementing Double Write:
def save_block(block):
  old_db.write(block) # Existing database
  new_sharded_db.write(block) # New sharded database
  1. Audit Log: Recording all changes via Kafka stream to verify data consistency
  2. Backfilling: Copying the entire database over three days using a powerful machine with 96 CPUs
  3. Cutover: The actual transition was surprisingly completed in just 5 minutes!

🌊 Building Data Lakes and Processing Systems

The sharded database was useful for handling real-time user requests, but separate solutions were needed for heavy tasks like analytics and machine learning.

The Need for a Data Lake

Notion's block data was doubling every 6-12 months. Initially, they started with a simple ELT pipeline using Fivetran to collect data from Postgres WAL into Snowflake. However, this approach faced two major problems:

  1. Operational Complexity: The overhead of managing 480 Fivetran connectors was too great.
  2. Increasing Costs: Notion's update-centric workload was inefficient to process in Snowflake.

Building an In-house Data Lake

Notion decided to build their own data lake with the following objectives:

  1. Build a storage for raw and processed data at scale
  2. Support fast, scalable, manageable, and cost-effective data collection and computation for all workloads
  3. Support AI, search, and other product requirements

Data Pipeline Design

Notion's data lake pipeline was designed as follows:

  1. Ingestion: Using Debezium CDC connectors to collect incrementally updated data from Postgres to Kafka
  2. Storage: Using Apache Hudi to store these updates from Kafka to Amazon S3
  3. Processing: Using Apache Spark to perform transformation, denormalization, and enrichment tasks
  4. Serving: Storing processed data back to S3 or delivering it to downstream systems

The key to this architecture is the active use of open-source tools to reduce costs while ensuring scalability and performance. Apache Spark efficiently processes large datasets, and Apache Kafka provides a reliable messaging system.

⚡ Second Expansion: Sharding Optimization

While the first sharding was successful, Notion's growth continued, and they faced new challenges.

Reaching Shard Capacity Limits

As shard utilization reached 90%, the system began to become unstable again. Notion took the following measures:

  1. Increased database machines from 32 to 96
  2. Reduced shards per machine from 15 to 5
  3. Used PostgreSQL's logical replication to copy data to the new system
  4. Efficiently distributed traffic through Pgbouncer

However, this approach created a new problem: reaching the connection limit of Pgbouncer.

Improving Connection Management

As a final solution, Notion adopted an approach of dividing shards into 5 logical groups to manage 24 databases. This allowed them to:

  1. Prevent connection limits and more easily isolate problems
  2. Test consistency between two databases through "dark reads"
  3. Gradually transition without downtime for users

🔍 Lessons from Notion's Data Management

From Notion's case, we can learn the following lessons:

  1. Deciding When to Shard: Sharding too early increases complexity, and sharding too late threatens system stability. Notion waited for clear signals: VACUUM process failure and TXID wraparound risk.
  2. Understanding Workload Characteristics: Notion's update-centric workload wasn't well-suited for traditional data warehouses like Snowflake. Understanding your workload characteristics and choosing appropriate solutions is important.
  3. Utilizing Open Source: Notion actively utilized open-source tools like Apache Spark, Apache Kafka, and Apache Hudi to reduce costs while ensuring scalability and performance.
  4. Gradual Transition Strategy: Notion's approach of migrating 20 billion blocks with just 5 minutes of downtime is safer and more efficient than a "big bang" approach.

Notion's case is a good example of how a rapidly growing startup can solve database scaling issues. Strategies like sharding, building data lakes, and utilizing open source can be useful references for other companies.

Conclusion

Notion has grown into a platform that reliably supports over 100 million users and more than 200 billion blocks by actively responding to technical challenges. The strategies applied in this process—database sharding, data lake construction, open-source utilization—provide valuable lessons for all rapidly growing technology companies.

Why not consider these large-scale data management technologies in your projects? Your service might experience explosive growth just like Notion!


#Notion #DatabaseSharding #PostgreSQL #DataLake #ApacheSpark #ApacheKafka #DataEngineering #LargeScaleDataProcessing #SystemScalability #OpenSource

#노션 #데이터베이스샤딩 #PostgreSQL #데이터레이크 #ApacheSpark #ApacheKafka #데이터엔지니어링 #대규모데이터처리 #시스템확장성 #오픈소스

반응형