Vercelでマルチテナントのサブドメインを動的に追加する方法
Vercel Domains APIを使って、テナント作成時にサブドメインを自動登録する方法とDNS設定をまとめました。
はじめに
サブドメインベースのマルチテナントSaaS({slug}.example.com のような構成)をVercelで運用する場合、テナントが増えるたびにサブドメインを追加する必要があります。
この記事では、Vercel Domains APIを使ってテナント作成時にサブドメインを自動登録する方法と、必要なDNS設定をまとめます。
前提: ドメイン構成
| ドメイン | 用途 |
|---|---|
example.com | LP |
app.example.com | ログイン・サインアップ |
{slug}.example.com | 各テナントのダッシュボード |
やること
- DNS側でワイルドカードCNAMEを設定する
- Vercel側にLP用・アプリ用のドメインを登録する
- テナント作成時にVercel Domains APIで個別サブドメインを登録する
1. DNS設定
DNSプロバイダで以下の3つのレコードを設定します。
| タイプ | ホスト名 | 値 |
|---|---|---|
| CNAME | example.com | vercelで表示される値 |
| CNAME | app.example.com | vercelで表示される値 |
| CNAME | *.example.com | cname.vercel-dns.com |
ポイントはワイルドカード(*)のCNAMEレコードです。これにより、どんなサブドメインでもVercelにルーティングされます。ただし、DNS側だけでは不十分で、Vercel側にもドメインの登録が必要です。
2. Vercelのドメイン設定
Vercelのプロジェクト設定(Settings → Domains)に以下を手動で追加します。
example.comapp.example.com
テナントのサブドメイン(demo.example.com など)は手動ではなく、APIで動的に追加します。
ワイルドカードドメインではなく個別登録にした理由
Vercelにも *.example.com をワイルドカードで登録する方法はありますが、個別登録にしました。
- テナント作成時に明示的に登録するため、意図しないサブドメインへのアクセスを防げる
- Vercel Domains APIで自動化すれば運用負荷は変わらない
3. Vercel Domains APIでサブドメインを自動登録
テナント作成時に、バックエンドからVercel Domains APIを呼び出してサブドメインを登録します。
POST https://api.vercel.com/v10/projects/{projectId}/domains
Authorization: Bearer {token}
Content-Type: application/json
{ "name": "demo.example.com" }
必要な環境変数
| 環境変数 | 取得方法 |
|---|---|
VERCEL_TOKEN | Vercelダッシュボード → Settings → Tokens |
VERCEL_PROJECT_ID | プロジェクト Settings → General |
VERCEL_TEAM_ID | チーム利用時のみ。チーム Settings → General |
実装のポイント
- 失敗してもテナント作成をブロックしない: ドメイン登録は try-catch で囲み、失敗はログに記録するだけにする。ユーザーのサインアップフローを止めないことが重要
- ローカル開発時はスキップ: 環境変数が未設定ならAPIコールをスキップする
ドメイン反映のタイムラグ
Vercel Domains APIでサブドメインを追加した後、実際にアクセス可能になるまで数秒〜十数秒のラグがあります。テナント作成直後にサブドメインへリダイレクトすると、エラーページが表示される可能性があります。
対策: フロントエンドでポーリング
テナント作成成功後、すぐにリダイレクトせず、サブドメインへのアクセスが可能になるまでポーリングで確認します。
- テナント作成APIを呼び出す
- 成功したら「ワークスペースを準備しています...」のローディング画面を表示
- バックグラウンドでサブドメインに対して
fetch(url, { method: 'HEAD', mode: 'no-cors' })を定期的に実行 - レスポンスが返ってきたらダッシュボードへリダイレクト
mode: 'no-cors' を使うのは、別オリジンへのリクエストでCORSエラーを回避するためです。opaque response(status=0)が返ればネットワーク的にはアクセス可能と判断できます。
まとめ
| 設定 | 内容 |
|---|---|
| DNS | *.example.com → cname.vercel-dns.com のワイルドカードCNAME |
| Vercel(固定) | LP用・アプリ用のドメインを手動登録 |
| Vercel(動的) | テナント作成時にDomains APIで個別サブドメインを登録 |
| タイムラグ対策 | フロントエンドでポーリングしてから遷移 |
DNS側のワイルドカード設定 + Vercel側の個別ドメイン登録の組み合わせで、テナント作成フローの中でサブドメインの追加を完全に自動化できます。