PostgreSQL vs MongoDB
オープンソースのリレーショナルデータベースの王者PostgreSQLと、柔軟なNoSQLドキュメント型のMongoDB。データモデルに応じて正しいデータベースをどう選ぶか?
自分のサーバーで稼働する、1986年から成熟を重ねてきたオープンソースのリレーショナルデータベース
本物のPostgreSQLの上に構築された、マネージド型オープンソースバックエンドプラットフォーム
この決定に唯一の正解はない。小規模なチームでスピードを最優先するなら、Supabaseが正しい選択だ。認証、ストレージ、リアルタイム、コネクションプーラーが用意されている。負荷が予測可能な場合、データ所在地の制約がある場合(17リージョンにトルコは含まれない)、あるいはコストがユーザー数に応じて増える場合は、自前ホスティングのPostgreSQLに軍配が上がる。注意点が一つある。公式ドキュメントは、セルフホストではマネージドのバックアップ/PITRが無効になると記している — 制御権とともにリストアリハーサルも引き受けることになる。バックアップを取ることが基準なのではなく、実際に復旧できることこそが基準だ。
| カテゴリー | Self-hosted PostgreSQL | Supabase |
|---|---|---|
| パフォーマンス | 8/10 | 8/10 |
| 学習のしやすさ | 5/10 | 8/10 |
| エコシステム | 9/10 | 8/10 |
| コミュニティ | 9/10 | 9/10 |
| 求人市場 | 8/10 | 7/10 |
| 将来性 | 8/10 | 8/10 |
# セルフホストPostgreSQL - WALアーカイブ + PITR構築 (postgresql.conf)
wal_level = replica
archive_mode = on
archive_command = 'test ! -f /var/backups/pg_wal_archive/%f && cp %p /var/backups/pg_wal_archive/%f'
max_wal_senders = 3
# ベースバックアップを取得 (pg_basebackup)
pg_basebackup -D /var/backups/base -Ft -z -P -U replicator -h localhost
# PITR: 特定の時刻へ復元する (recovery.signal + postgresql.conf)
# 1) ベースバックアップをリストアディレクトリに展開する
# 2) 以下の行をpostgresql.confに追加し、recovery.signalファイルを作成する
restore_command = 'cp /var/backups/pg_wal_archive/%f %p'
recovery_target_time = '2026-09-23 09:00:00+03'
# pg_hba.conf - アプリケーションサーバーからの接続のみ許可
host appdb app_user 10.0.0.5/32 scram-sha-256
-- SQL (psql): 拡張機能のインストール (完全な自由 - セルフホスト特有)
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS pg_cron;
# コネクションプーリング (PgBouncer, pgbouncer.ini)
[databases]
appdb = host=127.0.0.1 port=5432 dbname=appdb
[pgbouncer]
pool_mode = transaction
max_client_conn = 500
default_pool_size = 25-- SQL (Supabase SQL Editor): 1) テーブルを作成しRLSを有効化する (Data APIがこれを必須にする)
create table public.notes (
id uuid default gen_random_uuid() primary key,
user_id uuid references auth.users not null,
content text not null,
created_at timestamptz default now()
);
alter table public.notes enable row level security;
create policy "kullanicilar kendi notlarini okur"
on public.notes for select
using (auth.uid() = user_id);
create policy "kullanicilar kendi notlarini yazar"
on public.notes for insert
with check (auth.uid() = user_id);
// 2) supabase-jsでクエリを実行する (RLSは自動的に適用される)
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!
)
const { data: notes, error } = await supabase
.from('notes')
.select('id, content, created_at')
.order('created_at', { ascending: false })
// 3) Postgresクライアントでの接続文字列 (公式の "Endpoints and IP versions" テーブルより)
// Direct connection (永続的なバックエンド、pg_dump、マイグレーション向け):
// postgresql://postgres:[YOUR-PASSWORD]@db.[PROJECT-REF].supabase.co:5432/postgres
// Dedicated pooler (transactionモードのみ、有料プラン限定):
// postgresql://postgres:[YOUR-PASSWORD]@db.[PROJECT-REF].supabase.co:6543/postgres
// 文字列を手動で組み立てる場合: Dashboard > Connect画面からコピーする (shared poolerのホスト名はリージョンから導出できない)。この決定に唯一の正解はない。小規模なチームでスピードを最優先するなら、Supabaseが正しい選択だ。認証、ストレージ、リアルタイム、コネクションプーラーが用意されている。負荷が予測可能な場合、データ所在地の制約がある場合(17リージョンにトルコは含まれない)、あるいはコストがユーザー数に応じて増える場合は、自前ホスティングのPostgreSQLに軍配が上がる。注意点が一つある。公式ドキュメントは、セルフホストではマネージドのバックアップ/PITRが無効になると記している — 制御権とともにリストアリハーサルも引き受けることになる。バックアップを取ることが基準なのではなく、実際に復旧できることこそが基準だ。
無料相談を受けるSupabaseは標準的なPostgreSQLを使用しているため、`pg_dump`/`pg_dumpall`、またはネイティブなPostgresレプリケーションを使ってエクスポートできる。公式ドキュメントでは、プロジェクト間の移行手順をNode.jsスクリプトの例(認証・ストレージを含む)で説明している。Auth、Storage、Realtimeのようなsupabase固有のサービスをセルフホスト側で再構築すること(公式のセルフホストDocker Composeスタックを稼働させること)は別の作業であり、データ移行とサービスの機能パリティを揃えることは異なるステップだ。