11 KiB
11 KiB
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
// 알람 설정
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
export class MyDurableObject extends DurableObject {
async alarm(alarmInfo) {
// 알람 시간이 되면 자동으로 호출됨
// alarmInfo.retryCount: 재시도 횟수
// alarmInfo.isRetry: 재시도 여부 (boolean)
// 여기서 작업 수행, HTTP 호출, Storage API 사용 등 가능
// 다음 알람 설정도 가능
}
}
사용 사례
1. 배치 처리 (Batching)
10초 동안 받은 요청들을 모아서 한 번에 처리:
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) 구현
일정 시간 후 자동으로 데이터 삭제:
async fetch(request) {
// 요청마다 TTL 연장 (예: 1시간)
await this.ctx.storage.setAlarm(Date.now() + 3600000);
// 작업 수행...
}
async alarm() {
// TTL 만료 시 모든 데이터 삭제
await this.ctx.storage.deleteAll();
}
3. 주기적인 작업 실행
자동으로 다음 알람을 설정하여 주기적 실행:
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: 알람 실행 중 메모리 사용 시간 과금
주의사항
-
생성자에서
setAlarm호출 시: 이미 알람이 설정되어 있는지 먼저 확인해야 함- Hibernation에서 깨어날 때 생성자가
alarm()핸들러보다 먼저 호출됨 - 무한 루프 방지를 위해 체크 필요
- Hibernation에서 깨어날 때 생성자가
-
알람 덮어쓰기:
setAlarm()호출 시 기존 알람이 있으면 덮어씀 -
지연 가능성: 일반적으로 밀리초 내 실행되지만, 유지보수나 장애 복구 중에는 최대 1분까지 지연 가능
참고 자료
💰 Workers Paid 플랜 기본 비용
월 최소 $5.00 (아래 포함)
Workers 기본 포함 사항
| 항목 | 포함 한도 | 초과 시 비용 |
|---|---|---|
| Requests | 1천만 / 월 | $0.30 / 백만 |
| CPU Time | 3천만 CPU ms / 월 | $0.02 / 백만 CPU ms |
| Duration | 무제한 | 무료 |
📌 비용 절약 팁
D1
- 인덱스 활용: 스캔하는 rows 수를 줄여 rows_read 비용 절감
- 쿼리 최적화: 전체 테이블 스캔(
SELECT *) 지양 - 수평 확장: 10GB 이하의 여러 작은 데이터베이스로 분산 (무료)
KV
- 캐싱 전략: TTL 활용하여 불필요한 read 감소
- Bulk 작업: REST API bulk write 활용 (동일 비용)
- 만료 활용: 자동 만료로 delete 비용 절약
Durable Objects
- SQLite 백엔드 사용: 스토리지 과금이 아직 비활성화 (권장)
- WebSocket Hibernation API: Duration 비용 절감
- 비활성화 최적화: 요청 없을 때 자동 메모리 해제
- 수평 확장: 많은 작은 Objects로 분산 (무료 생성)
🔗 참고 자료
마지막 업데이트: 2025년 1월 17일