概要
短縮URLサービスは Bitly や TinyURL のような SaaS が有名ですが、以下のような理由で自前運用を検討するケースがあります。
- 自社ドメインで運用したい
- アクセスログを社外に出したくない
- 課金体系に縛られたくない
- SaaSのリンク数制限に引っかかる
こうした要件には 自己ホスト型 (Self-hosted) の OSS がフィットします。 本記事では代表的な OSS を比較し、AWS で構築した場合の費用感や、選定時にチェックしたい観点を整理します。
想定読者とこの記事のゴール
- 短縮URLサービスを自社で運用したいエンジニア・SRE
- マーケティング部門から「クリック分析できる自社ドメインのリンクが欲しい」と相談を受けた人
- 既存の Bitly 等から自前運用へ移行を検討している人
ゴールは次の3点です。
- 主要 OSS の特徴・できること/できないことを把握する
- AWS で構築した場合の概算費用を見積もる
- 運用に乗せるための検討ポイントを押さえる
まず全体像
短縮URL OSS は、大まかに次のような系統に分けられます。
flowchart LR
A[短縮URL OSS] --> PHP[PHP系]
A --> NODE[Node.js系]
A --> GO[Go系]
A --> EDGE[エッジ/サーバーレス系]
PHP --> Shlink
PHP --> YOURLS
PHP --> Polr
NODE --> Kutt
NODE --> Dub
GO --> Slash
EDGE --> Sink
classDef active fill:#e8f5e9,stroke:#2e7d32,color:#1b5e20;
classDef stable fill:#fff3e0,stroke:#ef6c00,color:#e65100;
classDef slow fill:#ffebee,stroke:#c62828,color:#b71c1c;
class Shlink,Kutt,Dub,Slash,Sink active;
class YOURLS stable;
class Polr slow;
色は「メンテナンスの活発度」のイメージです (緑:活発 / 橙:安定だが緩やか / 赤:更新が少なめ)。
各 OSS の概要
Shlink
- 公式: https://shlink.io/
- ドキュメント: https://shlink.io/documentation/
- GitHub: https://github.com/shlinkio/shlink
- 言語: PHP 8.x (Mezzio / Laminas)
- ライセンス: MIT
- GitHub Star: 約 4,000+
できること (Shlink)
- REST API / CLI / 公式 Web Client (別リポジトリで配布)
- 複数ドメイン対応 (1 インスタンスで複数ドメインの短縮URL)
- QRコード生成、タグ管理、UTM パラメータ自動付与
- 地理情報・デバイス・OS・リファラ別の詳細トラッキング
- Real-time 統計、Webhook、Matomo / Google Analytics 連携
- マルチユーザー対応 (v4.x 以降)
できない・苦手 (Shlink)
- 単体では UI が最低限。フル機能の管理画面は
shlink-web-clientを別途デプロイする必要がある - パスワード保護リンク、A/B テスト、リンクの有効期限内分岐などの高機能は標準ではない
企業内の業務用途や、メール配信・キャンペーン計測のような 真面目な計測用途 に向いています。
YOURLS
- 公式: https://yourls.org/
- ドキュメント: https://yourls.org/docs/
- GitHub: https://github.com/YOURLS/YOURLS
- 言語: PHP
- ライセンス: MIT
- GitHub Star: 約 9,000+
できること (YOURLS)
- 古参 (2009年〜) で安定感がある
- プラグインエコシステムが豊富 (
yourls-pluginsで公式・非公式が多数) - カスタム短縮 URL、QR コード、簡易統計、ブックマークレット
- PHP + MySQL のみで動作するため、レンタルサーバーでも動く
できない・苦手 (YOURLS)
- UI/UX は 2010 年代風で古い
- 標準の分析ダッシュボードは Bitly や Dub と比べて見劣りする
- マルチテナント・チーム機能は弱い
「とにかく軽く動かしたい」「PHP のレガシー環境がある」場合に依然として現実的な選択肢です。
Kutt
- 公式: https://kutt.it/
- ドキュメント: https://docs.kutt.it/
- GitHub: https://github.com/thedevs-network/kutt
- 言語: TypeScript / Node.js
- ライセンス: MIT
- GitHub Star: 約 8,000+
できること (Kutt)
- モダンな UI (React / Next.js ベース)
- カスタム短縮 URL、QR コード、リンクの有効期限、パスワード保護
- API トークンによる API 連携
- Telegram ボット、ブラウザ拡張機能
- ドメイン追加機能 (複数ドメイン対応)
できない・苦手 (Kutt)
- 単体ではアナリティクスがシンプル (国別・リファラ等の基本のみ)
- A/B テストやリンク内クローキングなどの高度な機能はない
- 大規模利用では Redis + PostgreSQL の運用知識が必要
「中小規模で OK、UI もまともで API も使いたい」のスイートスポット。
Dub
- 公式: https://dub.co/
- ドキュメント: https://dub.co/docs
- GitHub: https://github.com/dubinc/dub
- 言語: TypeScript / Next.js
- ライセンス: AGPL-3.0
- GitHub Star: 約 18,000+
できること (Dub)
- SaaS 品質のモダン UI / 機能 (Vercel 系開発者文化)
- 高機能リンク管理 (UTM ビルダー、リンククローク、Geo/Device ターゲティング、A/B テスト)
- リッチな OG プレビュー、リンクの有効期限、パスワード保護
- Tinybird ベースのリアルタイムアナリティクス
- チーム / ワークスペース / Webhook / 公開 API
- Conversion Tracking、決済連携 (Stripe)、Affiliate 等の機能も拡張中
できない・苦手 (Dub)
- 構成要素が多い (Postgres / Redis / Tinybird / S3 / Resend など) ため、純粋な「自己ホスト」のハードルは高い
- AGPL-3.0 なので、改修して SaaS 提供する場合はソース公開義務が発生する
- 小規模用途にはオーバースペック気味
「Bitly の代替を本気で内製したい」場合の最右翼。SaaS 版 dub.co を使う前提でも品質は最高クラス。
Polr
- 公式: https://polrproject.org/
- ドキュメント: https://docs.polrproject.org/
- GitHub: https://github.com/cydrobolt/polr
- 言語: PHP (Laravel)
- ライセンス: GPL-2.0
- GitHub Star: 約 4,000+
できること (Polr)
- シンプルかつ軽量
- API、カスタム短縮 URL、基本的なクリック統計
- マルチユーザー、API トークン
- Pro 版 (有料) で更に機能拡張可能
できない・苦手 (Polr)
- メンテナンスの活発度はやや低下傾向 (リリース間隔が長い)
- モダンな分析機能はなく、SaaS と比較すると見劣りする
- セキュリティ修正の追従が遅れがちなので、本番運用は要注意
「学習用、社内ツールでとりあえず動かす」用途には十分。
Slash (補足)
- GitHub: https://github.com/yourselfhosted/slash
- 言語: Go
- ライセンス: MIT
- GitHub Star: 約 5,000+
できること (Slash)
- 単一バイナリで動作する Go 製短縮URL/ブックマーク管理
- Docker で 1 コマンド起動
- 軽量で軽い、SQLite/PostgreSQL/MySQL に対応
- チーム共有のリンクコレクション機能あり
できない・苦手 (Slash)
- 大規模なクリック分析は弱い
- 短縮 URL に特化というよりは「チーム向けリンク共有」の色合いが強い
「個人 / 小チームで Docker 1 個で済ませたい」場合の選択肢。
Sink (サーバーレス系)
- GitHub: https://github.com/ccbikai/Sink
- 公式デモ: https://sink.cool/
- 言語: TypeScript (Nuxt 3)
- ライセンス: MIT
- GitHub Star: 約 6,000+
ここまで紹介してきた OSS は基本的に コンテナ / VM 上で動かす前提 ですが、Sink は Cloudflare ネイティブ (Workers + KV + Analytics Engine) で動作する点が大きく異なります。サーバーを 1 台も立てずに、wrangler deploy 1 コマンドで運用開始できます。
できること (Sink)
- Cloudflare アカウント1つで構築完了 (サーバー不要)
- グローバルにエッジ配信されるため リダイレクトの初動が非常に速い
- AI (Workers AI) によるスラッグ自動生成
- パスワード保護リンク、有効期限付きリンク
- リアルタイムアナリティクス (国 / デバイス / リファラ、Analytics Engine ベース)
- 個人利用なら 実質 $0 / 月 で運用可能 (Cloudflare の無料枠内)
できない・苦手 (Sink)
- Cloudflare ロックイン が強い。他クラウドへの移植性は低い
- KV は 結果整合性 なので、書き込み直後の世界規模での即時反映は保証されない
- Workers 無料枠は 10万 req/日、超過時は Workers Paid ($5/月〜) へ
- Webhook / 業務システム連携機能は控えめ
- 監査ログや細かな権限管理が必要なエンタープライズ要件には不向き
「個人ブログ・社内ツール・小さな SaaS のリンク管理で、運用コストをゼロに近づけたい」場合の決定版。
比較表
| 観点 | Shlink | YOURLS | Kutt | Dub | Polr | Slash | Sink |
|---|---|---|---|---|---|---|---|
| 言語 | PHP | PHP | Node.js | Next.js | PHP (Laravel) | Go | TypeScript (Nuxt 3) |
| ライセンス | MIT | MIT | MIT | AGPL-3.0 | GPL-2.0 | MIT | MIT |
| GitHub Star (概算) | 4k+ | 9k+ | 8k+ | 18k+ | 4k+ | 5k+ | 6k+ |
| メンテナンス活発度 | 高 | 中 | 高 | 非常に高 | 低〜中 | 高 | 高 |
| 初版リリース | 2016 | 2009 | 2017 | 2022 | 2014 | 2023 | 2024 |
| ホスティング形態 | コンテナ/VM | コンテナ/VM | コンテナ/VM | コンテナ/VM | コンテナ/VM | コンテナ/VM | サーバーレス (Cloudflare) |
| DB | MySQL/MariaDB/PostgreSQL/SQLite | MySQL/MariaDB | PostgreSQL | PostgreSQL | MySQL/MariaDB/SQLite | SQLite/PostgreSQL/MySQL | Cloudflare KV |
| Redis | 任意 | 不要 | 任意 | 必須 (Upstash 等) | 不要 | 不要 | 不要 |
| 必須外部サービス | なし | なし | なし | Tinybird, Resend, S3 等 | なし | なし | Cloudflare 一式 |
| 公式 Docker | あり | あり | あり | あり (開発用) | あり | あり | 不要 (Workers) |
| マルチドメイン | あり | プラグイン | あり | あり | 限定的 | あり | あり |
| マルチユーザー | あり (v4+) | プラグイン | あり | あり (ワークスペース) | あり | あり | 単一管理者 |
| カスタム短縮 URL | あり | あり | あり | あり | あり | あり | あり |
| QR コード | あり | プラグイン | あり | あり | プラグイン | なし | あり |
| パスワード保護 | なし | プラグイン | あり | あり | なし | なし | あり |
| 有効期限 | あり | プラグイン | あり | あり | あり | なし | あり |
| A/B テスト | なし | なし | なし | あり | なし | なし | なし |
| Geo/Device ターゲティング | なし | なし | なし | あり | なし | なし | なし |
| アナリティクス | 高機能 | 簡易 | 中程度 | 非常に高機能 | 簡易 | 簡易 | 中程度 (Analytics Engine) |
| 公開 API | あり (REST) | あり | あり (REST) | あり (REST) | あり | あり (gRPC/REST) | あり (REST) |
| 想定月額 (個人利用) | $30〜 (AWS) | $30〜 (AWS) | $30〜 (AWS) | $150〜 (AWS) | $30〜 (AWS) | $30〜 (AWS) | $0 (CF 無料枠) |
| 推奨用途 | 業務計測 | レガシー軽量 | 中規模・API 利用 | 大規模・SaaS 品質 | 学習・個人 | 小チーム | ゼロコスト運用 |
AWS で構築した場合の費用概算
東京リージョン (ap-northeast-1)、1 年継続利用 (On-Demand) の概算です。
為替・割引は時期により変動するため、目安としてご覧ください。
構成パターン
flowchart LR
subgraph User
U[利用者]
end
subgraph AWS
R53[Route 53<br/>独自ドメイン]
ALB[ALB / CloudFront]
APP[ECS Fargate or EC2<br/>短縮URL アプリ]
DB[(RDS<br/>MySQL/PostgreSQL)]
CACHE[(ElastiCache<br/>Redis)]
S3[(S3<br/>必要に応じて)]
end
U --> R53 --> ALB --> APP
APP --> DB
APP --> CACHE
APP --> S3
パターン 1: 最小構成 (個人〜小規模社内)
| 項目 | リソース | 想定月額 (USD) |
|---|---|---|
| Compute | EC2 t4g.small (1台、24h) | 約 $12 |
| DB | RDS db.t4g.micro (Single-AZ) | 約 $13 |
| ストレージ | EBS 20GB + RDS 20GB | 約 $5 |
| データ転送 | アウト 10GB/月 | 約 $1 |
| Route 53 | ホストゾーン + クエリ | 約 $1 |
| 合計 | 約 $32 / 月 (約 5,000 円) |
ALB を使わず、Nginx + Let’s Encrypt で EC2 直撮 (Elastic IP) の前提です。 Shlink / YOURLS / Polr / Slash / Kutt (Redis 無し設定) が現実的です。
パターン 2: 中規模 (社内全体・サービス公開)
| 項目 | リソース | 想定月額 (USD) |
|---|---|---|
| Compute | ECS Fargate 0.5 vCPU/1GB × 2 タスク | 約 $30 |
| ALB | 1 台 | 約 $22 |
| DB | RDS db.t4g.small Multi-AZ | 約 $55 |
| Redis | ElastiCache cache.t4g.micro | 約 $12 |
| データ転送 | アウト 100GB/月 | 約 $12 |
| CloudFront | 100GB/月 | 約 $10 |
| WAF | Basic + 数ルール | 約 $10 |
| Route 53 | ホストゾーン + クエリ | 約 $1 |
| 合計 | 約 $152 / 月 (約 23,000 円) |
Shlink / Kutt あたりに最適。冗長化と CDN を効かせた構成です。
パターン 3: 大規模 (Dub 級の SaaS 品質を内製)
| 項目 | リソース | 想定月額 (USD) |
|---|---|---|
| Compute | ECS Fargate 1 vCPU/2GB × 3 タスク | 約 $90 |
| ALB | 1 台 | 約 $22 |
| DB | RDS db.r6g.large Multi-AZ | 約 $370 |
| Redis | ElastiCache cache.t4g.small × 2 (HA) | 約 $50 |
| データ転送 + CloudFront | アウト 1TB/月 | 約 $120 |
| ログ/分析基盤 | Kinesis Firehose + S3 + Athena | 約 $50 |
| WAF + Shield Standard | 約 $20 | |
| Route 53 | ホストゾーン + クエリ | 約 $5 |
| 合計 | 約 $727 / 月 (約 11 万円) |
これに加えて Dub の場合は Tinybird (有料)、Resend (メール送信) などのサードパーティ費用が乗ります。
補足: 短縮URLは「リダイレクトだけ」と侮りがちですが、クリック計測の書き込み量がスループットのボトルネック になります。本格運用では Redis や ClickHouse / Tinybird のようなアナリティクス基盤の検討が早期に必要です。
パターン 4: サーバーレス (Cloudflare / Sink 利用)
AWS ではなく Cloudflare を使う前提で、Sink を採用する場合の費用感です。 EC2 / RDS / ALB といったリソースが一切不要になるため、桁が変わります。
flowchart LR
User[利用者] --> CF[Cloudflare<br/>エッジ]
CF --> W[Cloudflare Workers<br/>リダイレクト + 管理画面]
W --> KV[(Cloudflare KV<br/>slug → 元URL)]
W --> AE[(Analytics Engine<br/>クリックログ)]
W -.->|任意| AI[Workers AI<br/>slug 自動生成]
| 項目 | リソース | 想定月額 (USD) |
|---|---|---|
| 実行 | Cloudflare Workers (Free Plan) | $0 |
| ストレージ | Cloudflare KV (Free Plan) | $0 |
| 分析 | Analytics Engine (Free 枠) | $0 |
| 独自ドメイン | Cloudflare DNS 管理 | $0 |
| 合計 (小規模) | 約 $0 / 月 |
中規模以上 (1日 10 万リクエスト超 / KV 読み取り 10 万/日超) では Workers Paid プランへの移行が必要です。
| 項目 | リソース | 想定月額 (USD) |
|---|---|---|
| 実行 | Cloudflare Workers Paid | $5 |
| ストレージ | KV 追加分 (1000万 read で $0.50) | $1 〜 |
| 分析 | Analytics Engine 超過分 | $1 〜 |
| 合計 (中規模) | 約 10 / 月 |
AWS のパターン 2 (約 $152/月) と比較すると、Sink + Cloudflare は1桁安く済む ケースがほとんどです。 ただし、Cloudflare 依存・KV の結果整合性・監査ログの粒度 などのトレードオフがあるため、用途と要件次第で AWS 構成と使い分けるのが現実的です。
選定にあたって検討したい観点
機能比較だけで選ぶと後悔しがちなので、以下の観点も合わせて評価することをおすすめします。
1. ドメイン戦略
- 短縮 URL は 独自ドメイン (例:
go.example.co.jp) で発行するのが基本 - ブランド毀損や乗っ取り対策のため、ドメインの HSTS preload / CAA レコード / DMARC も同時に検討
- リンクは長期間生き残るので、捨てやすいドメインを使わない
2. リンクの永続性 (Link Persistence)
- 数年後にもクリックされる前提で、DB バックアップ・サービス停止時の代替案 を必ず用意
- 移行性を考えるなら、カスタム短縮 URL (slug) のエクスポート / インポート がしやすい OSS を選ぶ
- ShortIO 等の SaaS から移行する場合、CSV インポート可否を確認する
3. アナリティクスの粒度と保存期間
- クリックログは個人情報 (IP) を含むため、保存期間・匿名化方針 を最初に決める
- 大量のリンク + 大量のクリックを扱う場合、RDB だけでは負荷的に厳しい。カラムナ DB (Tinybird / ClickHouse) や Redis、Kinesis との組み合わせを検討
- GDPR / 個人情報保護法を意識するなら、IP のハッシュ化やジオロケーション粒度の制御が必要
4. セキュリティ
- 短縮 URL は フィッシングや C2 通信の踏み台 として悪用されやすい
- 対策として、事前 URL スキャン (Google Safe Browsing API, VirusTotal API)、禁止ドメインリスト、レート制限、短縮可能ユーザーの認証 をどう実装するか
- 公開短縮 URL を許す場合は、CAPTCHA + WAF + 通報フロー を必ず設計する
5. 可用性・SLO
- 短縮 URL がダウンすると、過去に配信したすべてのリンクが死ぬ
- 影響範囲が極めて大きいので、Multi-AZ / CDN キャッシュ / 障害時のフォールバック を初期から考慮
- CloudFront でリダイレクト結果を短時間キャッシュ (例: 60秒) するだけでも、原本ダウン時の被害が抑えられる
6. ライセンスと商用利用
- AGPL-3.0 (Dub) は SaaS として外部提供する場合にソース公開義務が生じる
- GPL-2.0 (Polr) も同様に注意が必要
- 社内利用にとどめる前提なら問題は少ないが、プロダクトに組み込んで顧客提供する場合は法務確認 を
7. 運用負荷
- 個人で運用するなら 依存サービスが少ない OSS (YOURLS / Slash / Shlink) が無難
- 「フルマネージドに近づけたい」なら App Runner / ECS Fargate + RDS のような構成にして、EC2 直運用を避ける
- 自動デプロイ・自動バックアップ・脆弱性パッチ自動適用までを最初の構築時に組み込んでおく
用途別おすすめ
flowchart TD
Q1{用途は?}
Q1 --> |個人・小規模| Q0{ランニングコストを<br/>ほぼゼロにしたい?}
Q1 --> |業務・社内全体| Q3{高度な分析が必要?}
Q1 --> |顧客向けSaaS| Q4{AGPL に同意できる?}
Q0 --> |Yes Cloudflare依存OK| Sink[Sink<br/>Cloudflare サーバーレス]
Q0 --> |No 自前運用したい| Q2{Docker 1 個で済ませたい?}
Q2 --> |Yes| Slash[Slash]
Q2 --> |No, UIも欲しい| Kutt[Kutt]
Q3 --> |Yes 詳細計測| Shlink[Shlink]
Q3 --> |No 軽くてOK| YOURLS[YOURLS]
Q4 --> |Yes| Dub[Dub]
Q4 --> |No | Dev[Dub のフォーク不可<br/>独自開発 or 他OSSベースを検討]
classDef rec fill:#e8f5e9,stroke:#2e7d32,color:#1b5e20;
class Sink,Slash,Kutt,Shlink,YOURLS,Dub rec;
利用イメージ (典型的なリクエストフロー)
短縮 URL の典型的なリクエスト / トラッキングは下記の流れになります。 Dub クラスではここに A/B テストや UTM 付与が挟まり、Shlink クラスでは Webhook で SIEM に転送、といったバリエーションが生まれます。
sequenceDiagram
participant User as ユーザー
participant CDN as CloudFront
participant App as 短縮URLアプリ
participant DB as DB (slug → 元URL)
participant Q as ログキュー / Redis
participant DW as 分析基盤
User->>CDN: GET https://go.example.co.jp/abc
CDN->>App: cache miss
App->>DB: SELECT * WHERE slug='abc'
DB-->>App: 元URL, 設定
App->>Q: クリックログ非同期送信 (IP, UA, Referer)
App-->>CDN: 302 Location: https://...
CDN-->>User: 302 Location: https://...
Q-->>DW: 集約・集計
Note over App,DB: 必要に応じて<br/>パスワード/期限/Geo分岐
まとめ
| シーン | おすすめ |
|---|---|
| とにかく無料で運用したい (Cloudflare OK) | Sink |
| とりあえず動かしたい / レガシー PHP 環境 | YOURLS |
| 業務での真面目な計測・複数ドメイン | Shlink |
| モダンUI + API 連携、中規模社内 | Kutt |
| Bitly 代替を本気で内製 (顧客提供) | Dub |
| 学習・個人ブログ用途 | Polr |
| Docker 1 個でチームのリンク共有 | Slash |
短縮 URL は「ドメインの寿命 = リンクの寿命」と「クリックログのスケール」が落とし穴です。 選定の前に “5 年後もこのドメインを維持できるか / 月間クリックがどこまで伸びるか” を見積もる ことを強くおすすめします。
最終的には、
- ランニングコスト最優先 (Cloudflare 依存OK) → Sink
- 個人・社内ツール (自前運用) → Shlink / Kutt / Slash
- 顧客向け本格運用 → Dub (or 自社開発)
が最初の選択肢になるはずです。