# Cloudflare D1, KV, Durable Objects 비용 정책 정리 > 공식 문서 기준으로 작성 (2025년 1월) --- ## 📊 D1 (Serverless SQL Database) ### 무료 플랜 (Workers Free) | 항목 | 무료 한도 | 제한 | |------|----------|------| | **Rows Read** | 5백만 / 일 | 일일 한도 초과 시 쿼리 실행 불가 | | **Rows Written** | 10만 / 일 | 일일 한도 초과 시 쿼리 실행 불가 | | **Storage** | 5 GB (총계) | 한도 도달 시 데이터 삭제 후 추가 가능 | | **데이터베이스 수** | 최대 10개 | - | | **데이터베이스 최대 크기** | 500 MB | - | | **Time Travel (복구)** | 7일 | - | - 무료 한도는 매일 00:00 UTC에 초기화 - 데이터 전송(egress) 비용 없음 ### 유료 플랜 (Workers Paid) | 항목 | 포함 한도 | 초과 시 비용 | |------|----------|-------------| | **Rows Read** | 250억 / 월 포함 | **$0.001** / 백만 rows | | **Rows Written** | 5천만 / 월 포함 | **$1.00** / 백만 rows | | **Storage** | 5 GB 포함 | **$0.75** / GB-월 | | **데이터베이스 수** | 최대 50,000개 | - | | **데이터베이스 최대 크기** | 10 GB | - | | **Time Travel (복구)** | 30일 | - | - 월별 한도는 구독 갱신일 기준으로 초기화 - 데이터 전송(egress) 비용 없음 - Read replication은 추가 비용 없음 (rows_read/rows_written 기준으로만 과금) ### 주요 특징 - **Scale-to-zero**: 쿼리를 실행하지 않으면 컴퓨팅 비용 없음 - **Rows 계산**: 쿼리가 스캔한 행 수로 계산 (반환된 행이 아님) - **인덱스**: 쓰기 시 최소 1개 추가 row written (인덱스 업데이트) - **빈 데이터베이스**: 약 12 KB 스토리지 사용 --- ## 🗂️ Workers KV (Key-Value Store) ### 무료 플랜 (Workers Free) | 항목 | 무료 한도 | 제한 | |------|----------|------| | **Keys Read** | 10만 / 일 | 일일 한도 초과 시 작업 실패 | | **Keys Written** | 1,000 / 일 | 일일 한도 초과 시 작업 실패 | | **Keys Deleted** | 1,000 / 일 | 일일 한도 초과 시 작업 실패 | | **List Requests** | 1,000 / 일 | 일일 한도 초과 시 작업 실패 | | **Storage** | 1 GB | - | | **네임스페이스 수** | 1,000개 | - | - 무료 한도는 매일 00:00 UTC에 초기화 - 동일 키 쓰기 제한: 1회 / 초 ### 유료 플랜 (Workers Paid) | 항목 | 포함 한도 | 초과 시 비용 | |------|----------|-------------| | **Keys Read** | 1천만 / 월 포함 | **$0.50** / 백만 | | **Keys Written** | 100만 / 월 포함 | **$5.00** / 백만 | | **Keys Deleted** | 100만 / 월 포함 | **$5.00** / 백만 | | **List Requests** | 100만 / 월 포함 | **$5.00** / 백만 | | **Storage** | 1 GB 포함 | **$0.50** / GB-월 | ### 주요 특징 - **데이터 전송(egress) 비용 없음** - **Bulk 작업**: REST API를 통한 bulk write도 각 키당 1회 write로 계산 - **Key 만료**: 만료된 키는 과금 없음 (delete 작업으로 계산 안됨) - **Key 크기**: 최대 512 bytes - **Value 크기**: 최대 25 MiB --- ## 💾 Durable Objects ### 무료 플랜 (Workers Free) - **SQLite 스토리지 백엔드만 사용 가능** - Key-Value 스토리지 백엔드는 사용 불가 #### Compute (컴퓨팅) | 항목 | 무료 한도 | |------|----------| | **Requests** | 10만 / 일 | | **Duration** | 13,000 GB-s / 일 | #### SQLite Storage | 항목 | 무료 한도 | |------|----------| | **Rows Read** | 5백만 / 일 | | **Rows Written** | 10만 / 일 | | **SQL Storage** | 5 GB (총계) | - 무료 한도는 매일 00:00 UTC에 초기화 - 최대 Durable Object 클래스: 100개 ### 유료 플랜 (Workers Paid) #### Compute (컴퓨팅) | 항목 | 포함 한도 | 초과 시 비용 | |------|----------|-------------| | **Requests** | 100만 / 월 포함 | **$0.15** / 백만 | | **Duration** | 400,000 GB-s 포함 | **$12.50** / 백만 GB-s | **Requests 포함 항목:** - HTTP requests - RPC sessions - WebSocket messages (20:1 비율로 계산) - Alarm invocations **Duration 계산:** - 128 MB 메모리 할당 기준 - Durable Object가 메모리에 활성화된 시간 (wall-clock time) - 비활성(inactive) 상태에서는 과금 없음 #### SQLite Storage Backend (권장) | 항목 | 포함 한도 | 초과 시 비용 | |------|----------|-------------| | **Rows Read** | 250억 / 월 포함 | **$0.001** / 백만 rows | | **Rows Written** | 5천만 / 월 포함 | **$1.00** / 백만 rows | | **SQL Storage** | 5 GB 포함 | **$0.20** / GB-월 | > ⚠️ **주의**: SQLite 백엔드의 스토리지 과금은 아직 활성화되지 않음 (향후 사전 공지 후 활성화 예정) #### Key-Value Storage Backend (Paid 전용) | 항목 | 포함 한도 | 초과 시 비용 | |------|----------|-------------| | **Read Request Units** | 100만 / 월 포함 | **$0.20** / 백만 | | **Write Request Units** | 100만 / 월 포함 | **$1.00** / 백만 | | **Delete Requests** | 100만 / 월 포함 | **$1.00** / 백만 | | **Storage** | 1 GB 포함 | **$0.20** / GB-월 | **Request Unit 계산:** - 1 Request Unit = 4 KB 데이터 - 9 KB write = 3 write request units - List 작업은 검사한 데이터 양 기준 (80 KB 반환 = 20 read units) ### 주요 특징 - **최대 Durable Object 클래스**: 500개 (Paid) / 100개 (Free) - **계정당 최대 스토리지**: 50 GB (요청으로 증가 가능) - **개별 Object당 최대 스토리지**: 무제한 - **CPU 제한**: 요청당 30초 (증가 가능) - **빈 SQLite DB**: 약 12 KB 스토리지 사용 --- ## ⏰ Durable Objects Alarms 기능 ### Alarms란? Durable Objects Alarms는 미래의 특정 시간에 Durable Object를 자동으로 깨워서 작업을 실행할 수 있게 하는 스케줄링 기능입니다. ### 주요 특징 - **Object당 1개의 알람**: 각 Durable Object는 한 번에 하나의 알람만 설정 가능 - **최소 한 번 실행 보장**: At-least-once 실행 보장 - **자동 재시도**: 실패 시 exponential backoff로 자동 재시도 - 첫 실패 후 2초 지연부터 시작 - 최대 6회까지 재시도 - **밀리초 단위 정밀도**: 밀리초 단위로 스케줄링 가능 (일반적으로 설정 시간 후 수 밀리초 내 실행) ### API 메서드 #### Storage Methods ```javascript // 알람 설정 await ctx.storage.setAlarm(Date.now() + 10000); // 10초 후 실행 await ctx.storage.setAlarm(scheduledTimeMs); // 밀리초(UNIX epoch 기준) // 현재 알람 확인 const alarmTime = await ctx.storage.getAlarm(); // 설정된 알람 시간 반환 (없으면 null) // 알람 삭제 await ctx.storage.deleteAlarm(); ``` #### Handler Method ```javascript export class MyDurableObject extends DurableObject { async alarm(alarmInfo) { // 알람 시간이 되면 자동으로 호출됨 // alarmInfo.retryCount: 재시도 횟수 // alarmInfo.isRetry: 재시도 여부 (boolean) // 여기서 작업 수행, HTTP 호출, Storage API 사용 등 가능 // 다음 알람 설정도 가능 } } ``` ### 사용 사례 #### 1. 배치 처리 (Batching) 10초 동안 받은 요청들을 모아서 한 번에 처리: ```javascript async fetch(request) { // 알람이 설정되어 있지 않으면 10초 후로 설정 let currentAlarm = await this.storage.getAlarm(); if (currentAlarm == null) { await this.storage.setAlarm(Date.now() + 10000); } // 요청을 저장 await this.storage.put(requestId, requestData); } async alarm() { // 10초 동안 모인 모든 요청을 한 번에 처리 const requests = await this.storage.list(); await fetch('https://api.example.com/batch', { method: 'POST', body: JSON.stringify(Array.from(requests.values())) }); await this.storage.deleteAll(); } ``` #### 2. TTL (Time To Live) 구현 일정 시간 후 자동으로 데이터 삭제: ```javascript async fetch(request) { // 요청마다 TTL 연장 (예: 1시간) await this.ctx.storage.setAlarm(Date.now() + 3600000); // 작업 수행... } async alarm() { // TTL 만료 시 모든 데이터 삭제 await this.ctx.storage.deleteAll(); } ``` #### 3. 주기적인 작업 실행 자동으로 다음 알람을 설정하여 주기적 실행: ```javascript async alarm() { // 작업 수행 await this.doPeriodicTask(); // 다음 알람 설정 (예: 5분 후) await this.ctx.storage.setAlarm(Date.now() + 300000); } ``` ### Cron Triggers와의 차이점 | 특징 | Alarms | Cron Triggers | |------|--------|---------------| | **개수 제한** | Object당 1개, 전체 무제한 | Worker당 최대 3개 | | **설정 방식** | 프로그래밍 방식 (코드에서 직접) | 설정 파일/대시보드 | | **정밀도** | 밀리초 단위 | 분 단위 (최소 1분) | | **스케일** | Object별로 독립적 스케줄링 | Worker 전체에 대한 스케줄 | | **동적 스케줄링** | 런타임에 동적 설정 가능 | 배포 시 고정 | ### 과금 - **각 `setAlarm()` 호출**: SQLite 백엔드는 1 row written, KV 백엔드는 1 write request unit - **`alarm()` handler 실행**: 1 request로 계산 (Requests 과금 항목) - **Duration**: 알람 실행 중 메모리 사용 시간 과금 ### 주의사항 1. **생성자에서 `setAlarm` 호출 시**: 이미 알람이 설정되어 있는지 먼저 확인해야 함 - Hibernation에서 깨어날 때 생성자가 `alarm()` 핸들러보다 먼저 호출됨 - 무한 루프 방지를 위해 체크 필요 2. **알람 덮어쓰기**: `setAlarm()` 호출 시 기존 알람이 있으면 덮어씀 3. **지연 가능성**: 일반적으로 밀리초 내 실행되지만, 유지보수나 장애 복구 중에는 최대 1분까지 지연 가능 ### 참고 자료 - [Durable Objects Alarms API](https://developers.cloudflare.com/durable-objects/api/alarms) - [Alarms API 사용 예제](https://developers.cloudflare.com/durable-objects/examples/alarms-api/) - [Durable Objects Alarms 발표 블로그](https://blog.cloudflare.com/durable-objects-alarms/) --- ## 💰 Workers Paid 플랜 기본 비용 **월 최소 $5.00** (아래 포함) ### Workers 기본 포함 사항 | 항목 | 포함 한도 | 초과 시 비용 | |------|----------|-------------| | **Requests** | 1천만 / 월 | $0.30 / 백만 | | **CPU Time** | 3천만 CPU ms / 월 | $0.02 / 백만 CPU ms | | **Duration** | 무제한 | 무료 | --- ## 📌 비용 절약 팁 ### D1 1. **인덱스 활용**: 스캔하는 rows 수를 줄여 rows_read 비용 절감 2. **쿼리 최적화**: 전체 테이블 스캔(`SELECT *`) 지양 3. **수평 확장**: 10GB 이하의 여러 작은 데이터베이스로 분산 (무료) ### KV 1. **캐싱 전략**: TTL 활용하여 불필요한 read 감소 2. **Bulk 작업**: REST API bulk write 활용 (동일 비용) 3. **만료 활용**: 자동 만료로 delete 비용 절약 ### Durable Objects 1. **SQLite 백엔드 사용**: 스토리지 과금이 아직 비활성화 (권장) 2. **WebSocket Hibernation API**: Duration 비용 절감 3. **비활성화 최적화**: 요청 없을 때 자동 메모리 해제 4. **수평 확장**: 많은 작은 Objects로 분산 (무료 생성) --- ## 🔗 참고 자료 - [D1 Pricing](https://developers.cloudflare.com/d1/platform/pricing/) - [KV Pricing](https://developers.cloudflare.com/kv/platform/pricing/) - [Durable Objects Pricing](https://developers.cloudflare.com/durable-objects/platform/pricing/) - [Workers Pricing](https://developers.cloudflare.com/workers/platform/pricing/) --- **마지막 업데이트**: 2025년 1월 17일