テーマを切り替える

一人開発のデータベース選び:D1・Postgres・R2・S3・SQLite

Easton editorial illustration: central four-way data-routing hub, structured relational database cylinder, object-storage bucket holding file sheets, single local database disk, sealed backup archive box

"CloudflareのD1料金ページはrows read/written、保存容量、インデックスが走査行数に与える影響、Freeの日次上限到達時の挙動を説明しています。"

プロジェクトにはusersテーブル、orders、usage_events、ユーザーがアップロードしたuploads/2026/06/report.pdf、cache:daily-stats、ローカル開発用のlocal-dev.sqliteがあります。それぞれをどこに置くべきでしょうか。業務上の事実をオブジェクトストレージに入れると、バックアップ、検索、エクスポートがすぐ扱いにくくなります。D1で絞り込み列にインデックスを付けなければrows readが無料枠を急速に消費し、Paidでは超過料金も発生します。まずデータの種類から考えます。

データ配置表:何をどこに保存するか

一人開発でも、データの性質によって保存先は変わります。業務上の事実には検索、関連、権限制御が必要です。イベントログは安定した書き込みと保管コストが重要です。オブジェクトファイルにはダウンロード権限、ライフサイクル、トラフィックに合う料金体系が要ります。構造化検索と権限が必要か、アクセス頻度はどれくらいか、転送料に敏感かを確認します。

次の表を最初の判断に使えます。

7種類のデータと保存先

データの種類具体例推奨する保存先判断基準
業務上の事実users、orders、契約権利、決済記録Supabase Postgresを優先、単純な場合はD1構造化クエリ(SELECT/JOIN)、権限(RLS)、プランに合うバックアップ/時点復元、監査性
イベントログusage_events、操作記録、アクセス統計エッジ書き込みならD1、監査用途ならPostgres高頻度書き込みと単純な検索。通常の分析イベントは復旧優先度を下げられるが、セキュリティ/課金イベントは確実に保管
オブジェクトファイルuploads/2026/06/report.pdf、生成物、エクスポート、画像CloudflareならR2、AWSならS3、またはSupabase StorageDB blobにしない。R2の転送、S3のエコシステム、Supabase Auth/Postgres連携で選択
キャッシュcache:daily-stats、短期状態、一時計算Cloudflare KV、D1、ローカルSQLite高頻度アクセスで通常は期限切れ/再生成が可能。エッジはKV/D1、ローカルはSQLite
ローカル開発データlocal-dev.sqlite、テストデータ、単一ユーザー管理画面SQLiteファイル単一ユーザー、権限システムなし、コピーして実行しやすい
軽量なエッジデータWorkersのカウンター、設定表、ドメイン対応D1またはCloudflare KVWorkersネイティブ、軽い関係、読み取り中心
バックアップDB dump、エクスポートスナップショットR2/S3とローカルコピーR2の転送料、S3のガバナンス/ライフサイクル、障害に備える別コピー

業務上の事実をPostgresから始める理由

ユーザー、注文、契約権利、決済はプロジェクトの中核です。失うと顧客の利用権や売上に影響します。必要なのは次の機能です。

  • 構造化クエリ:関係データベースはSELECT、JOIN、WHERE、ORDER BYを扱えます。オブジェクトストレージは扱えません。
  • 権限制御:Supabase PostgresはRow Level Securityでクライアント向けアクセスを制御できます。D1には現在ネイティブRLSがありません。
  • バックアップと復元:Supabase Pro、Team、Enterpriseには日次バックアップがあります。PITRは別途有効化する有料アドオンです。D1 Time TravelはWorkers Freeで7日、Paidで30日保持します。
  • 監査:決済や権利の変更は、Postgresのtriggerと監査テーブルで実装しやすくなります。

Supabase Postgresは制限版の抽象層ではありません。各projectには完全なPostgres databaseがあり、Auth、Storage、Realtime、Edge Functionsがその周囲に構築されています(Supabase Database公式ドキュメント)。通常のPostgres機能を利用できます。

イベントと業務レコードを分ける

usage_events、操作、アクセス統計は業務上の事実と性質が異なります。

  • 書き込み頻度は高い一方、代表的なクエリは期間指定と集計です。
  • 監査対象ではない分析イベントは復旧優先度を下げられますが、保持期間と損失許容度を明示します。セキュリティ、課金、権利イベントは通常のpage viewと同じに扱えません。
  • 高頻度書き込みはrows writtenとstorage quotaを消費するため、コストが重要です。

境界は次の通りです。

  • user_idとactionを結び付ける監査記録ならPostgresを使います。
  • page view countのようなカウンターや再生成可能な分析信号ならD1またはKVを使えます。

オブジェクトファイルをDBに入れない

アップロード、生成結果、エクスポート、画像をDBのblob列に入れるべきではありません。

  • バックアップ費用:すべてのblobがDBバックアップに入り、時間と容量が増えます。
  • クエリ負荷:大きなオブジェクトと関係行を混ぜると、転送、cache、backup、保守が重くなり、幅広いクエリが誤ってファイル本体を返しやすくなります。
  • CDN配信:オブジェクトストレージはCDN、cache policy、署名付きdownloadに接続しやすい一方、DB blobは通常application proxyを要します。
  • 転送料:DB blobの配信はDBとapplicationの帯域を使います。R2から直接Internetへ転送する場合、R2 egress料金はありません。S3はregionとdestinationで変わります。

DBにはuploads/2026/06/report.pdfのようなobject keyだけを保存し、ファイル本体をR2、S3、Supabase Storageに置きます。

キャッシュとローカル開発データ

cache:daily-stats、短期状態、一時計算には次の特徴があります。

  • 読み書きが多く、通常は期限切れまたは再生成が可能です。セキュリティに関わるsessionは整合性、期限、失効を別に定義します。
  • 再生成可能なcacheは通常、業務DBのbackupに含めません。sessionの失効記録などは独自の永続化方針が必要です。
  • エッジではlatencyが重要です。

選択肢は次の通りです。

  • Workersの軽量エッジcacheにはCloudflare KVまたはD1を使います。
  • ローカル開発にはSQLiteファイルまたはmemory cacheを使います。

local-dev.sqliteは単一ユーザーで権限システムのない用途です。

  • SQLiteはlocal application dataとapplication file向けです(SQLiteを使う場面)。
  • client/server databaseと同じ問題を解くものではありません。SQLiteはlocal/single-user、Postgresはshared/multi-userを重視します。

軽量なエッジデータとバックアップ

Workersのカウンター、小さな設定表、ドメイン対応にはD1またはKVが出発点になります。

  • ネイティブアクセス:Worker bindingまたはHTTP APIを使い、別のconnection poolを運用しません。
  • 軽い関係:複雑なJOINや大きなforeign-key graphに依存しない単純なschemaです。
  • 読み取り中心:readが多く、writeは比較的少ない用途です。

バックアップのエクスポートには低コストな取り出しと独立したコピーが必要です。

  • R2から直接Internetへdownloadする場合、R2 egress料金はありません。
  • S3にはObject Lock、複数のarchive class、lifecycle managementがあります。
  • account/provider障害に備え、localまたは別providerにもコピーします。本番と同じ場所だけに復元データを置くのは不十分です。

D1:Workersネイティブのserverless database

D1はSQLite SQL semanticsを持つCloudflareのmanaged serverless databaseです(D1概要)。主な機能は次の通りです。

  • Time Travel:Workers Freeは過去7日、Paidは30日の任意の1分へ復元できます。復元はDBをその場で上書きするため、時刻を確認します。
  • Read replication:読み取りlatencyを下げ、read-heavy workloadのthroughputを拡張します。
  • Workers/HTTP API:別のDB connection poolを運用せず、bindingまたはHTTP APIから使えます。
  • Built-in disaster recovery:DB historyとrecovery systemをCloudflareが管理します。

適する用途:Workersネイティブで読み取り中心

D1が合うのは次の用途です。

  • Workers/Pages上のprojectで、queryのたびに別platformへ接続したくない場合。
  • 設定、counter、domain mappingなど、複雑な関係が少ない軽量relational data。
  • read replicationで読み取りを拡張できるread-heavy workload。
  • Workers、R2、KV、Vectorizeをすでに利用し、同じecosystemにrelational layerが必要な場合。

適しにくい用途は次の通りです。

  • 成熟したpermission systemとRLSが必要なmulti-user SaaS。
  • 制約、監査、検証済みの復元が必要な注文と契約権利。通常はPostgresが安全な出発点ですが、復元期間はmanaged planとadd-onで変わります。
  • Postgresのtrigger/監査patternが必要なaudit-heavy system。

rows read課金:返却行ではなく走査行

D1はrows read、rows written、storageで課金します。rows readは返却行数ではなくqueryが走査した行数です。

2026年7月時点の公式料金ページは次の枠と料金を示しています。公開前や大きな設計判断の前に再確認してください。

項目Workers FreeWorkers Paid
Rows read5M/day最初の25B/monthを含む
Rows written100K/day最初の50M/monthを含む
Storage合計5 GB最初の5 GBを含み、超過は$0.75/GB-month
Rows read超過利用不可$0.001/million rows read
Rows written超過利用不可$1/million rows written
Egress/bandwidth追加料金なし追加料金なし

50,000行のordersにSELECT * FROM orders WHERE user_id = ? LIMIT 20を実行し、user_idにindexがなければ、20行を返すためにtableの大部分を走査する可能性があります。rows readは20ではなく50,000に近づきます。

返却件数が少なくても、indexのないfilterはtable全体を走査します。結果件数から推測せず、実際のqueryが返すmeta.rows_readを確認します。

インデックス設計とクエリ効率

rows readを抑える手順です。

  1. CREATE INDEX idx_user_id ON orders(user_id);のようなindexを作り、対象subsetだけを走査させます。値はmeta.rows_readで確認します。
  2. 必要なcolumnだけを取得してresponse payloadと結合を減らします。ただしD1はcolumn数ではなく走査行数を数えます。rows readを減らす鍵はindexとfilterです。
  3. rows_readと返却行を比べます。query metaとdashboardにrows read/writtenがあるため、効率を計算してfull-table scanを見つけられます。

index設計の要点です。

  • user_idやcreated_atなどWHEREで使うcolumnにindexを付けます。
  • order_idやproduct_idなどJOIN keyにindexを付けます。
  • 不要なindexは避けます。INSERT/UPDATEでindex rowも書き込む場合があります。
  • D1 dashboardでrows readが異常に多いqueryを定期確認します。

D1無料枠とアップグレードの兆候

Workers Freeの現在の上限です。

  • 1日5M rows read。平均50K rows readのqueryは日次上限まで約100回です。
  • 1日100K rows written。write-heavy workloadは早く消費します。
  • account合計5 GB storageです。

Workers Paidを検討する兆候です。

  • 日次rows readが5Mに近づく。Freeは上限後にqueryが失敗し、Paidは月25Bを含み超過課金です。
  • 日次rows writtenが100Kに近づく。Paidは月50Mを含みます。
  • storageが5 GBを超える。Paid超過は$0.75/GB-monthです。

D1はWorkersに近い軽量relational data向けであり、高頻度writeや大容量storageすべての既定値ではありません。成長に合わせてrows read、rows written、storageを監視します。

Supabase Postgres:BaaSの実用的な既定値

各Supabase projectには制限版ではない完全なPostgres databaseがあります(Supabase Database公式ドキュメント)。Auth、Storage、Realtime、Edge Functionsが周囲に構築され、複雑なquery、foreign key、trigger、transaction、MVCC、extensionを利用できます。

RLSでクライアントアクセスを制御する

Row Level SecurityはSupabase Postgresの大きな利点です。従来はDBをserverだけに公開し、clientはAPI経由でqueryします。RLSはpolicyとkeyを正しく設定すれば、client queryに行単位の権限を適用できます。

RLSが担うことは次の通りです。

  • Access control:認証userとuser_idが一致するrowだけ見せるpolicyを定義できます。
  • Audit design:RLSはaccess boundaryを定義します。誰がいつ何をしたかは、audit table、trigger、logging systemで別に記録します。
  • 重複する権限codeの削減:policyをDBに置けますが、serverはidentity検証、privileged key保護、高権限操作のreviewを続けます。

業務上の事実、権限が重要なapplication、multi-user SaaS、注文、契約権利に向きます。RLSはDBレベルの境界であり、schemaやaudit設計の代わりではありません。

バックアップと復元

2026年7月時点のSupabase公式プランは次の通りです。

項目FreeProTeam
Database sizeprojectごとに500 MBを含むprojectごとに8 GB、超過課金projectごとに8 GB、超過課金
Price$0$25/month$599/month
Automatic backups含まない日次、7日保持日次、14日保持
PITR含まない有料add-on、7日保持は約$100/monthから有料add-on、7日保持は約$100/monthから

ここから三つの実務判断ができます。

  • Free projectはplatform backupを復元方針にできません。supabase db dumpまたはpg_dumpを定期実行し、別拠点に保存します。
  • Pro/Teamは日次backupがありますが、前回backup後の変更を最大1日分失う可能性があります。
  • PITRはProの標準機能ではありません。少なくともSmall computeが必要で、7/14/28日の保持期間ごとに別料金です。

DB容量だけでupgradeを決めません。注文と権利にはRPO、RTO、復元訓練の頻度を先に決め、日次backupで足りるかPITRが必要か判断します。

D1との比較:権限と復元

項目D1Supabase Postgres
位置付けWorkersネイティブserverless databaseManaged Postgres BaaS
権限制御ネイティブRLSなしRLSでclient queryを制御
復元Time Travel:Free 7日、Paid 30日Pro/Team/Enterpriseは日次backup、PITRは有料add-on
適用先Workersの軽量relational data業務上の事実、multi-user SaaS、注文、権利
課金rows read/writtenとstoragedatabase storage、compute、plan usage

併用もできます。

  • D1にread-heavyなedge設定、counter、domain mappingを置きます。
  • Supabase Postgresにuser、order、契約権利、決済記録を置きます。

SaaS toolの設定とcounterをD1に、userと権利をPostgresに置く構成です。D1はWorkersに近く、Postgresは成熟した権限、制約、復元手段を提供します。

R2:R2側のegress料金がないオブジェクトストレージ

R2はCloudflareのS3-compatible object storageです。R2、Workers API、S3 API、r2.devからInternetへ直接転送する場合、R2 egress料金はありません(R2料金)。bucketに接続した別のmetered serviceが課金する場合はあります。upload、生成結果、exportに向きますが、egress freeはstorageとoperationまで無料という意味ではありません。

Class A/B Operationsの課金

R2はstorage、Class A operations、Class B operationsで課金します。Infrequent Accessにはretrieval feeもあります。

2026年7月時点の料金です。

項目Free tierStandardInfrequent Access
Storage10 GB-month/month$0.015/GB-month$0.01/GB-month
Class A operations1M/month$4.50/million$9.00/million
Class B operations10M/month$0.36/million$0.90/million
Data retrievalなしなし$0.01/GB
Internet egressFreeFreeFree
Minimum storage durationなしなし30日

operationの分類です。

  • Class A:高価なgroupで、PutObject、CopyObject、ListObjects、lifecycle tier transitionなどです。writeとlistが中心です。
  • Class B:安価なgroupで、GetObject、HeadObject、HeadBucketなどです。readが中心です。
  • 無料operation:DeleteObject、DeleteBucket、AbortMultipartUploadです。

R2無料枠の誤解

10 GB-monthは無制限storageではありません。

  • Storage:billing periodに保持した容量でありtrafficではありません。超える場合はPaid利用またはcleanupが必要です。
  • Class A:月1M operationsですが、batch uploadは早く消費します。
  • Class B:月10M operationsで多くのreadを賄えますが、高trafficの画像originは超える可能性があります。

Infrequent Accessは30日のminimum storage durationがあります。早く削除してもminimum chargeは残るため、backupや長期object向けで、一時出力には向きません。

適する用途:アップロードと生成結果

R2が合う用途です。

  • uploads/2026/06/report.pdf、画像、文書などのuser upload。downloadが多い用途に向きます。
  • 生成report、export、画像処理結果。
  • 低コストで取り出したいDB dumpとsnapshot。
  • Workers、D1、KV、Vectorizeを利用するproject。

適さない用途です。

  • structured queryとaccess controlが必要なuser/orderなどの業務上の事実。
  • S3 Object Lock、より多いstorage tier、AWSネイティブのcross-bucket/cross-region replicationが必要なworkload。

R2とS3の比較

項目R2S3
Internet egressR2側は無料、接続するmetered serviceは課金の場合ありregion、destination、usageで変わるため現行AWS料金表で確認
StorageStandardは$0.015/GB-monthStandardやGlacierを含む複数tier
EcosystemWorkers/PagesネイティブLambdaを含む広いAWS連携
Governancelifecycle、Standard/IA、Queues event notificationObject Lock、複数Glacier class、lifecycle、Replication、複数event destination
適用先Cloudflare ecosystem、egress-sensitive deliveryAWS ecosystem、governance、data lake、enterprise application

R2を選ぶ場面です。

  • downloadが多くegress costが重要です。
  • applicationがWorkers/Pages上で動きます。

S3を選ぶ場面です。

  • Lambda、data lake、enterprise workflowがAWS serviceに依存します。
  • Object Lock、より多いGlacier class、cross-region replication、AWSネイティブIAM governanceが必要です。
  • CloudWatch、IAM、batch operationなど広いAWS toolchainに価値があります。

R2とS3は完全な代替関係ではありません。Cloudflare上のproductがCDN fileと生成物をR2に置き、governance対象archiveをS3に置く構成も可能です。

S3:AWSエコシステムとガバナンス

Amazon S3はdata lake、website、mobile application、backup/restore、archive、enterprise application、IoT、analyticsに使うobject storage serviceです(Amazon S3 User Guide)。次の機能があります。

  • Standard、Intelligent-Tiering、Glacier、Glacier Deep Archiveなどのstorage class。
  • objectを自動で移行または削除するlifecycle rule。
  • WORM保持で上書き/削除を防ぐObject Lock。
  • recovery、latency、governance向けのSame-Region/Cross-Region Replication。
  • IAM、bucket policy、Block Public Access。
  • LambdaなどAWS destinationへのevent notification。

適する用途:AWS連携とガバナンス要件

S3が合う用途です。

  • Lambda、EC2、RDS、DynamoDBをすでに使うproduct。
  • Object Lock、archive class、正式なretention controlが必要な場合。
  • AWS analytics serviceに依存するdata lake/IoT pipeline。
  • lifecycle ruleを使う長期backup、restore、archive。

適しにくい用途です。

  • user downloadが多くegress costに敏感な場合。対象region、destination、cache、volumeの現行AWS料金を使って見積もります。
  • applicationがCloudflareネイティブで、Workers/PagesからR2へ直接アクセスできる場合。

S3とR2:エコシステムとガバナンスの深さ

S3の主な利点はAWS連携とgovernance機能の幅です。

  • Event destination:S3 Event NotificationsはSNS、SQS、Lambda、EventBridgeへ送れます。R2もobject-create/deleteをCloudflare Queuesへ送り、WorkerまたはHTTP pullで処理できます。
  • Storage class:S3は複数のGlacier archive classを持ち、R2は現在StandardとInfrequent Accessが中心です。
  • Object Lock:保持期間中の上書き/削除をWORMで防止します。
  • Replication:同regionまたは別regionのbucketへobject、metadata、tagをcopyできます。

S3を選ぶ場面です。

  • Lambda、data lake、enterprise applicationがAWS連携に依存します。
  • Object Lock、Glacier class、lifecycle governanceが必要です。
  • 長期archiveでGlacier familyが有利です。

R2を選ぶ場面です。

  • user uploadと生成fileが頻繁にdownloadされます。
  • Workers/Pagesが主要runtimeです。

CDN fileと生成結果をR2に、governance対象backupをS3に置く併用もできます。providerを一つに固定せず、data typeとaccess patternで決めます。

SQLite:ローカルと組み込みを優先する

SQLiteはlocal application data、application file、低〜中traffic site、analysis、cacheに向きます(SQLiteを使う場面)。client/server SQL databaseと直接競合する製品ではありません。client/server systemはshared repository、concurrency、centralization、controlを重視し、SQLiteはlocal/single-userでcopy可能な単一fileを重視します。

適する用途:単一ユーザーツールとローカルbackend

SQLiteが合う用途です。

  • single-user tool、local dashboard、analysis utility、小規模game、one-file dataset。
  • CAD、finance、media management softwareのapplication file format。
  • 低〜中traffic website。SQLite公式は100K hits/day未満なら一般に良好と説明しますが、保守的な目安であり性能保証ではありません。hardware、query complexity、concurrent writeで変わります。
  • local-dev.sqliteのようなlocal development data。
  • durable shared stateが不要なcacheとtemporary calculation。

適しにくい用途です。

  • permission、concurrent write、auditが必要なmulti-user SaaS。
  • 成熟したbackup/point-in-time recoveryが必要なorderとsubscription entitlement。
  • SQLiteは多readerを許してもwriterは一つなので、write-heavy concurrency。

SQLiteとPostgres:移行の兆候

項目SQLitePostgres
位置付けlocal data、application fileshared client/server repository
適用先single-user tool、小規模game、local dashboardmulti-user SaaS、order、subscription entitlement
Concurrencyone writer、many readersMVCCによるmultiple writers
Permissionbuilt-in user managementなしRLSとuser/role management
Cost独立DB server不要self-host/managed plan、compute、backupで変動

SQLiteからPostgresへ移る兆候です。

  1. single-user toolがmulti-user SaaSになり、permission systemが必要になる。
  2. 複数userまたはinstanceが同じstateを同時更新する。
  3. paymentによりorder/entitlementのauditと検証済みrecoveryが必要になる。
  4. users/roles/permissions modelにDBレベルのaccess controlが必要になる。

個人用analysis dashboardはSQLiteのままで構いません。複数の有料customerがserviceを共有するなら、Postgresが明確な境界です。

SQLiteはPostgresの代替ではない

SQLite公式もclient/server SQL databaseを置き換えるものではないと説明しています。

  • SQLiteはlocal、single-user、単一fileをcopyできるsimplicityを重視します。
  • Postgresはshared multi-user repository、concurrent state change、payment-critical recordを重視します。

SQLiteは独立DB serverを必要としません。Postgresのcostはself-host/managed plan、compute、storage、backupで変わります。どちらも検証済みのrestore processが必要です。

SQLiteを選ぶ場面です。

  • paymentやpermission systemのないlocal utilityと小規模game。
  • development fixtureとtemporary data。
  • write concurrencyが低いpersonal siteとdocumentation tool。

Postgresを選ぶ場面です。

  • order、subscription、permissionを持つmulti-user SaaS。
  • operationとentitlement changeを監査する場合。
  • configurable point-in-time recoveryが必要なbusiness record。

併用もできます。local developmentや再生成可能cacheはSQLite、production business factはPostgresに置きます。

避けるべき三つの誤り

代表的な誤りは、業務上の事実をobjectとして保存すること、D1のscan-based billingを無視すること、R2無料枠を無制限と考えることです。復元が難しくなり、queryが遅くなり、costの予測性が下がります。

誤り1:業務上の事実をオブジェクトストレージへ置く

users、orders、監査対象のusage_eventsをR2/S3に置くべきではありません。object storageにはrelational query、constraint、row-level permission、DB audit patternがありません。

具体的な問題です。

  • SELECT/JOIN不可:object storageはkey-basedです。SELECT * FROM orders WHERE user_id = ? LIMIT 20に答えるにはapplicationがorder objectをlist/downloadする必要があります。
  • 復元が難しい:file collectionはtransactional order historyではありません。SQL dumpやmanaged point-in-time systemの方が一貫したDB recovery pathになります。
  • exportが遅い:DB queryは条件に合うrecordをstreamできますが、object-per-order設計では多くのfileを走査します。

業務上の事実はDB、fileはobject storageへ置きます。DBは安定したobject keyを保存し、R2、S3、Supabase Storageがfileを保持します。

誤り2:rows read課金を見落とす

D1は返却行ではなく走査行を数えます。indexのないfilterはresult countよりはるかに多いrows readを消費します。

50,000行のordersでSELECT * FROM orders WHERE user_id = ? LIMIT 20を実行し、user_idにindexがなければ多数の行を走査します。実際の課金対象はmeta.rows_readで分かります。Freeは日次5M上限後にqueryが失敗し、Paidは月次包含量を超えると課金されます。

対策です。

  1. 実際のfilter columnにCREATE INDEX idx_user_id ON orders(user_id);のようなindexを付けます。
  2. EXPLAIN QUERY PLANとmeta.rows_readでfull-table scanが残っていないか確認します。
  3. 必要なcolumnだけ選びpayloadを抑えますが、D1はcolumnではなくrowを数える点を忘れません。

誤り3:R2無料枠を無制限と考える

R2無料枠は現在、Standard storage 10 GB-month、月1M Class A、月10M Class Bです。無制限ではありません。

よくある誤解です。

  • 10 GB-monthは期間中のstored capacityで、transfer allowanceではありません。
  • PutObjectはClass A operationです。総容量が小さくてもbatch作成で枠を消費します。
  • Infrequent Accessには30日のminimum durationがあり、早く削除してもminimum chargeが発生します。

storageとoperation countを監視し、古いoutputを計画的にexpireし、一時fileにはInfrequent Accessを使いません。短期dataならlocal SQLiteまたはcacheの方が適します。

まとめ

保存先は、業務上の事実、イベント、オブジェクト、キャッシュ、ローカル開発データ、軽量エッジデータ、バックアップという種類で選びます。Supabase Postgresはrelation constraint、RLS、設定可能なrecovery、audit patternを持つため業務データの起点になります。D1はWorkersネイティブの軽量relational data、R2/S3はobject、SQLiteはsingle-user local dataに向きます。

最初のversionを安全にする三つの行動です。

  1. 各objectを分類し、query、permission、access frequency、cost要件を記録します。
  2. D1のfilter columnにindexを付け、rows-read metricで結果を検証します。
  3. business recordをobject storageに置かず、unindexed scanを避け、R2はstorageだけでなく全無料枠を見積もります。

次の記事ではpaymentとuser systemを扱います。payment orderにはPostgresのconstraint、backup、auditが、user entitlementとpermissionにはRLSと検証済みrecoveryが必要です。

保存先がまだ曖昧なら、データ配置表とseries前半のarchitecture principle、backend stack、deploymentの記事へ戻ります。system boundaryを決めてからstorageの役割を細分化してください。

一人開発プロジェクトの保存先を決める

データの棚卸しから復元テストまで、6段階でデータベースとオブジェクトストレージの役割を分けます。

  1. 1

    ステップ 1: データを棚卸しする

    users、orders、usage_events、uploads、cache、ローカルファイル、バックアップを製品別に分けず列挙します。
  2. 2

    ステップ 2: データの種類を付ける

    各項目を業務上の事実、イベント、ファイル、キャッシュ、ローカルデータ、バックアップに分類し、期限切れや再生成が可能か記録します。
  3. 3

    ステップ 3: 整合性と権限を定義する

    トランザクション、制約、RLS、同時書き込み、監査、複数インスタンス共有の要件からPostgresかD1かを判断します。
  4. 4

    ステップ 4: アクセス量と課金要因を見積もる

    D1 rows read/written、R2 Class A/B operations、容量、読み取り頻度、出力転送料を見積もります。
  5. 5

    ステップ 5: 安定した参照を設計する

    object key、owner、status、metadataはデータベースに、ファイル本体はオブジェクトストレージに置き、keyの命名を安定させます。
  6. 6

    ステップ 6: バックアップと移行を検証する

    エクスポート、別拠点コピー、削除猶予、復元訓練を用意し、移行ではmetadata、ファイル、読み取り経路の順に切り替えます。

FAQ

一人開発ではD1とSupabase Postgresのどちらを先に選ぶべきですか?
Workers/Pages中心で関係が単純かつ読み取りが多い軽量データならD1を検討できます。ユーザー、注文、契約、権限、複雑なクエリには通常Supabase Postgresが適します。
R2とS3には何を保存しますか?
画像、PDF、エクスポート、バックアップ、生成結果などのオブジェクトファイルです。データベースにはmetadata、owner、status、object keyを保存し、大きなファイル本体は置きません。
SQLiteで最初のSaaSを運用できますか?
単一マシンのツールや書き込み競合が少ないサイトには使えます。複数インスタンス共有、複雑な権限、決済権利、多数の同時書き込みが必要ならPostgresを検討します。
ユーザーのアップロードをデータベースに保存できますか?
通常は勧めません。ファイル本体をR2、S3、Supabase Storageに置き、参照と権限をDBに保存すると、バックアップ、配信、CDN、削除方針を管理しやすくなります。
D1のrows read課金とは何ですか?
返却行数ではなく走査行数を数えます。インデックスのない条件は少数の結果でも多数の行を走査するため、インデックス、EXPLAIN QUERY PLAN、meta.rows_readで確認します。
Cloudflare R2の無料枠で足りますか?
Standard storage、Class A/B operations、読み取り頻度を合わせて見積もります。現在は10 GB-month、月1M Class A、月10M Class Bが無料ですが、価格は変わり得てInfrequent Accessには適用されません。

13分で読めます · 公開日: 2026年10月9日

コメント

GitHubアカウントでログインしてコメントできます

Easton BlogEaston Blog