言語を切り替える
テーマを切り替える

Workers + KV で作る自分だけの短縮URLサービス:入門から実戦まで

なぜ短縮URLサービスを自作するのか?

正直に言うと、私はあるサードパーティの短縮URLサービスを2年近く愛用していました。しかしある朝、全ての短縮リンクが無効になっていることに気づきました——サービスが突然終了したのです。SNSでシェアした数百のリンクが全て404エラーになりました。

その時、「自分だけの短縮URLサービスを作れないか?」と考えました。データが自分の手元にあれば、突然のサービス終了に怯える必要はありませんし、機能も好きにカスタマイズできます。

そこで見つけたのが Cloudflare Workers + KV という組み合わせです。

  • 無料枠が凄い:毎日10万リクエストまで無料。
  • 爆速:世界200以上のエッジノードで実行されるため、どこからアクセスしても速い。
  • 簡単:数行のコードで動き出す。
  • データ所有権:データは自分のKVストレージにあるので安心。

この記事では、私が実際に構築した手順をシェアします。カスタム短縮コードの指定や、簡易的なアクセス解析機能も含め、コピペで動くコード付きで解説します。

なぜ Workers + KV なのか?

Cloudflare Workers とは?

簡単に言えば、Cloudflareのエッジネットワーク上で動く「サーバーレス関数」です。コードを書けば、世界中のサーバーに自動でデプロイされ、ユーザーに最も近い場所で実行されます。
太っ腹な無料枠

  • 1日10万リクエスト
  • 1リクエストあたり10msのCPU時間
  • 個人利用なら十分すぎます。

KVストレージの強み

KV (Key-Value) ストレージは、エッジコンピューティングに最適化されたNoSQLデータベースです。

  • 読み込みが超高速:データがエッジにキャッシュされるため、読み込みは爆速(中央値12ms)です。
  • 世界規模の同期:書き込みは少し時間がかかりますが(最大60秒)、一度書き込めば世界中で読めます。
  • 相性抜群:短縮URLは「短縮コード(Key)」から「元のURL(Value)」を引くだけのシンプルな仕組みなので、KVに最適です。
10万回/日
無料枠
毎日のリクエスト数
12ms
KV読込速度
エッジキャッシュによる高速応答
200+
拠点数
グローバルなエッジネットワーク

第三者サービスとの比較

特徴一般的な短縮URLサービス自作 Workers + KV
データ所有権サービス側に依存完全にご自身のもの
カスタマイズ制限あり自由自在
持続性サービス終了リスクありCloudflareが続く限り安泰
広告挟まることがあるなし
コスト有料プランが必要な場合もほぼ無料

ゼロから作る短縮URLサービス

では、手を動かしていきましょう。

準備作業

1. Cloudflareアカウント作成
cloudflare.com で無料アカウントを作成します。

2. Wrangler CLIのインストール
ローカルで開発するためのツールです。

npm install -g wrangler
# または
yarn global add wrangler

インストール後、ログインします:

wrangler login

3. プロジェクト作成

mkdir my-shortlink
cd my-shortlink
wrangler init

JavaScriptプロジェクトとして作成します。

Step 1: KVネームスペースの作成

データベースの「テーブル」にあたるものを作ります。

# 本番用
wrangler kv:namespace create SHORTLINKS
# プレビュー用(ローカルテストなどで使用)
wrangler kv:namespace create SHORTLINKS --preview

実行すると id が表示されるので、これをメモして wrangler.toml に書き込みます。

name = "my-shortlink"
main = "src/index.js"
compatibility_date = "2025-12-01"

# KV設定を追加
[[kv_namespaces]]
binding = "SHORTLINKS"
id = "<あなたの本番用ID>"
preview_id = "<あなたのプレビュー用ID>"

binding = "SHORTLINKS" とすることで、コード内で env.SHORTLINKS としてアクセスできるようになります。

Step 2: コードの実装

src/index.js に以下のコードを書きます。

export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const path = url.pathname.slice(1); // 先頭のスラッシュを削除

    // ルートアクセス時
    if (path === '') {
      return new Response('短縮URLサービスへようこそ!', { status: 200 });
    }

    // GETリクエスト: リダイレクト処理
    if (request.method === 'GET') {
      // KVから元のURLを取得
      const targetUrl = await env.SHORTLINKS.get(path);
      
      if (targetUrl) {
        // 統計情報の更新(非同期で実行し、リダイレクトを遅らせない)
        const statsKey = `stats:${path}`;
        env.SHORTLINKS.get(statsKey).then(count => {
          const newCount = (parseInt(count) || 0) + 1;
          env.SHORTLINKS.put(statsKey, newCount.toString());
        });
        
        // 301リダイレクト
        return Response.redirect(targetUrl, 301);
      } else {
        return new Response('リンクが見つかりません', { status: 404 });
      }
    }

    // POSTリクエスト: 短縮URL作成
    if (request.method === 'POST') {
      try {
        const body = await request.json();
        const { url: targetUrl, code } = body;

        if (!targetUrl) {
          return new Response('URLが必要です', { status: 400 });
        }

        // 短縮コードの決定(指定がなければランダム生成)
        const shortCode = code || generateRandomCode();

        // 重複チェック
        const existing = await env.SHORTLINKS.get(shortCode);
        if (existing) {
          return new Response('そのコードは既に使用されています', { status: 409 });
        }

        // KVに保存
        await env.SHORTLINKS.put(shortCode, targetUrl);

        return new Response(JSON.stringify({
          shortCode,
          shortUrl: `${url.origin}/${shortCode}`,
          targetUrl
        }), {
          status: 201,
          headers: { 'Content-Type': 'application/json' }
        });

      } catch (error) {
        return new Response('リクエストエラー', { status: 400 });
      }
    }

    return new Response('Method Not Allowed', { status: 405 });
  }
};

// ランダムコード生成関数(6文字)
function generateRandomCode(length = 6) {
  const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
  let code = '';
  for (let i = 0; i < length; i++) {
    code += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  return code;
}

Step 3: ローカルテスト

wrangler dev

サーバーが起動したら(通常 http://localhost:8787)、テストしてみましょう。

短縮URL作成:

curl -X POST http://localhost:8787 \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

レスポンス例:

{
  "shortCode": "aBc123",
  "shortUrl": "http://localhost:8787/aBc123",
  "targetUrl": "https://example.com"
}

アクセス確認:
ブラウザで http://localhost:8787/aBc123 にアクセスすると、https://example.com にリダイレクトされるはずです。

Step 4: デプロイ

wrangler deploy

これで世界中に公開されました!発行されたURL(例: https://my-shortlink.subdomain.workers.dev)を使ってサービスを開始できます。

Step 5: カスタムドメイン(推奨)

workers.dev ドメインではなく、自分のドメイン(例: link.example.com)を使いたい場合は:

  1. Cloudflareダッシュボードの「Workers & Pages」へ。
  2. 作成したWorkerを選択。
  3. Settings > Triggers > Custom Domains からドメインを追加。
    これで、さらにプロフェッショナルな短縮URLサービスの完成です。

発展機能

1. セキュリティ対策

誰でも短縮URLを作れる状態は危険(イタズラやフィッシングに使われる可能性がある)です。簡易的なAPIトークン認証を入れましょう。

// POSTリクエスト処理の先頭に追加
const token = request.headers.get('Authorization');
if (token !== `Bearer ${env.API_TOKEN}`) {
  return new Response('Unauthorized', { status: 401 });
}

wrangler secret put API_TOKEN でトークンを設定し、クライアント側から送信させます。

2. 有効期限(TTL)の設定

一時的なリンクを作りたい場合、KVの有効期限機能を使えます。

// 24時間 (86400秒) で消える設定
await env.SHORTLINKS.put(shortCode, targetUrl, {
  expirationTtl: 86400
});

3. アクセス統計API

保存した統計情報を取得するエンドポイントを追加します。

// GETリクエスト処理に追加
if (path.startsWith('stats/')) {
  const code = path.replace('stats/', '');
  const count = await env.SHORTLINKS.get(`stats:${code}`);
  return new Response(JSON.stringify({ code, visits: count || 0 }));
}

http://yoursite.com/stats/abc123 にアクセスすると、クリック数が分かります。

まとめ

Cloudflare Workers + KV は、個人開発者がツールを自作するのに最強のプラットフォームです。サーバー管理不要、爆速、そして無料。
今回の短縮URLサービスは、コード量も少なく、初めてのWorkersプロジェクトとしても最適です。ぜひ試してみてください。自分のデータを自分で持つ安心感は、何物にも代えがたいですよ。

Workers + KV 短縮URLサービス構築ガイド

環境構築からデプロイまでのステップバイステップ手順

⏱️ Estimated time: 30 min

  1. 1

    Step1: 環境準備

    Cloudflareアカウント作成、Wrangler CLIのインストール、およびログインを完了します。
  2. 2

    Step2: プロジェクトとKV作成

    wrangler init でプロジェクトを作成し、wrangler kv:namespace create でKVストレージを確保。IDを設定ファイルに記述します。
  3. 3

    Step3: コーディング

    GETリクエストでのリダイレクト処理、POSTリクエストでの短縮URL生成・保存処理を実装します。アクセス統計機能もここに追加可能です。
  4. 4

    Step4: テストとデプロイ

    wrangler dev でローカル動作確認を行い、問題なければ wrangler deploy で世界中に公開します。

FAQ

完全に無料ですか?
はい、1日10万リクエスト、KVの読み込み10万回/日までは無料です。個人の短縮URLサービスとしては十分すぎる容量です。
KVの反映に時間がかかると聞きましたが?
KVは「結果整合性」モデルを採用しているため、書き込みが全世界のノードに行き渡るのに最大60秒ほどかかる場合があります。ただし、短縮URLを作ってその瞬間に世界中の人がアクセスすることは稀なので、実用上は問題になりません。
自分のドメインを使えますか?
はい、Cloudflareダッシュボードからカスタムドメインをバインドすることで、`link.mydomain.com/xyz` のようなURLで運用可能です。SSL証明書も自動で設定されます。

3 min read · 公開日: 2025年12月1日 · 更新日: 2026年1月22日

コメント

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

関連記事