※本記事には広告(A8・楽天アフィリエイト)リンクが含まれる場合があります。

「APIにキャッシュを入れたい」「レート制限を実装したい」「でもRedisサーバーを立てるのは面倒くさい」——個人開発者なら一度は感じたことがあるジレンマではないでしょうか。

そこで登場するのが Upstash です。Upstashはサーバーレス・ペイパーユース型のRedisサービスで、インフラ管理ゼロ・無料枠あり・Cloudflare Workersとの相性抜群という、個人開発者にとって夢のような組み合わせを実現します。

本記事では、Upstash Redisのセットアップから、キャッシュ実装・APIレート制限・セッション管理まで、実際に動くコード例を交えながら解説します。

Upstashとは? なぜ個人開発者に最適なのか

Upstashは2021年に登場した、HTTP REST APIベースのサーバーレスRedisサービスです。通常のRedisはTCP接続が必要ですが、UpstashはHTTP経由でアクセスできるため、Cloudflare WorkersやVercel Edge Functionsなどのサーバーレス環境でも問題なく使えます。

Upstashの料金体系:個人開発者に嬉しい無料枠

プラン 料金 デイリーコマンド数 最大データサイズ
Free $0 10,000回/日 256MB
Pay as you go $0.2/10万コマンド 無制限 〜100GB
Pro 2K $10/月〜 無制限 10GB〜

個人開発の初期フェーズなら無料枠で十分です。月数千〜数万アクセス程度なら無料でずっと使えます。スケールしてきたらペイパーユースで移行できるのも安心です。

Cloudflare Workers KVとの違い:何を使うべき?

「Cloudflare Workers KVがあるのに、なぜUpstashが必要なの?」という疑問を持つ方も多いでしょう。以下の表で比較します。

機能 Cloudflare KV Upstash Redis
データ構造 Key-Valueのみ 文字列・Hash・List・Set・Sorted Set
書き込み反映 最大60秒の遅延 即時
INCR / カウンター ❌ 非対応 ✅ 対応
TTL設定 ✅ 対応 ✅ 対応
レート制限ライブラリ ❌ なし ✅ @upstash/ratelimit
Cloudflare以外でも使える ❌(CF専用) ✅ Vercel・Next.jsでも使える

まとめると:単純なキャッシュ → KVで十分。カウンター・レート制限・ランキング → Upstash一択です。

セットアップ:Upstashアカウント作成からCloudflare Workers連携まで

ステップ1:Upstashデータベースを作成

まず upstash.com でアカウントを作成します(Googleアカウントでログイン可)。

  1. コンソールにログイン → 「Redis」タブを選択
  2. 「Create Database」をクリック
  3. データベース名(例: my-app-cache)を入力
  4. リージョンを選択(日本向けなら ap-northeast-1 = 東京)
  5. 「Create」で完了

作成後、コンソールで「REST API」タブを開くと、接続に必要な UPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN が確認できます。

ステップ2:Cloudflare Workersプロジェクトに接続

既存のCloudflare Workersプロジェクト(またはHonoプロジェクト)にUpstashを追加します。

npm install @upstash/redis

次に、シークレットをWranglerで登録します(コードに直接書かないこと)。

wrangler secret put UPSTASH_REDIS_REST_URL
# プロンプトが出たら、UpstashコンソールのREST URLを貼り付ける

wrangler secret put UPSTASH_REDIS_REST_TOKEN
# 同様にトークンを貼り付ける

これで準備完了です。コード内では以下のように接続します。

import { Redis } from '@upstash/redis/cloudflare'

type Bindings = {
  UPSTASH_REDIS_REST_URL: string
  UPSTASH_REDIS_REST_TOKEN: string
}

// Cloudflare Workers環境では fromEnv() が便利
const redis = Redis.fromEnv(env)

// または明示的に指定
const redis = new Redis({
  url: env.UPSTASH_REDIS_REST_URL,
  token: env.UPSTASH_REDIS_REST_TOKEN,
})

広告・楽天アフィリエイト

開発者向けガジェット

PC周辺機器を楽天市場でチェック。

楽天ポイント還元

楽天市場を見る →

広告・楽天アフィリエイト

メカニカルキーボード

打鍵感で選ぶ開発者向けキーボード。

楽天ポイント還元

キーボードを楽天で見る →

実践1:APIレスポンスのキャッシュ実装

最も基本的なユースケースが「APIレスポンスのキャッシュ」です。外部APIへのリクエストを毎回発行するのは遅く、コストもかかります。Upstashを使えば、一度取得したデータをRedisに保存し、TTL(有効期限)内は高速で返せます。

import { Hono } from 'hono'
import { Redis } from '@upstash/redis/cloudflare'

type Bindings = {
  UPSTASH_REDIS_REST_URL: string
  UPSTASH_REDIS_REST_TOKEN: string
}

const app = new Hono<{ Bindings: Bindings }>()

app.get('/api/weather/:city', async (c) => {
  const city = c.req.param('city')
  const redis = Redis.fromEnv(c.env)
  const cacheKey = `weather:${city}`

  // キャッシュチェック
  const cached = await redis.get<string>(cacheKey)
  if (cached) {
    return c.json({ data: JSON.parse(cached), cached: true })
  }

  // キャッシュミス → 外部APIから取得
  const res = await fetch(
    `https://api.weatherapi.com/v1/current.json?key=YOUR_KEY&q=${city}`
  )
  const data = await res.json()

  // 30分間キャッシュ(ex = seconds)
  await redis.set(cacheKey, JSON.stringify(data), { ex: 1800 })

  return c.json({ data, cached: false })
})

export default app

ctx.waitUntil() を使うと、レスポンスを先にユーザーへ返してからバックグラウンドでキャッシュ更新できます。レイテンシをさらに改善したい場合に有効です。

// バックグラウンドでキャッシュ更新(レスポンスをブロックしない)
c.executionCtx.waitUntil(
  redis.set(cacheKey, JSON.stringify(data), { ex: 1800 })
)
return c.json({ data, cached: false })

パイプラインで複数コマンドを一括実行

複数のキーを同時に取得・更新するとき、1コマンドずつ実行するとHTTPラウンドトリップが増えて遅くなります。パイプラインを使えば1回のリクエストにまとめられます。

const pipeline = redis.pipeline()
pipeline.get('config:theme')
pipeline.get('config:locale')
pipeline.incr('metrics:pageviews')

const [theme, locale, views] = await pipeline.exec()
// 1回のHTTPリクエストで3つのコマンドを実行!

実践2:APIレート制限を5分で実装する

個人開発でAPIを公開するとき、レート制限は必須のセキュリティ施策です。スパムや過剰なリクエストからサービスを守ります。Upstashは @upstash/ratelimit という専用ライブラリを提供しており、数行で実装できます。

npm install @upstash/ratelimit
import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis/cloudflare'
import { Hono } from 'hono'

type Bindings = {
  UPSTASH_REDIS_REST_URL: string
  UPSTASH_REDIS_REST_TOKEN: string
}

const app = new Hono<{ Bindings: Bindings }>()

app.use('/api/*', async (c, next) => {
  const redis = Redis.fromEnv(c.env)

  // スライディングウィンドウ: 10秒に10リクエストまで
  const ratelimit = new Ratelimit({
    redis,
    limiter: Ratelimit.slidingWindow(10, '10 s'),
    analytics: true, // Upstashコンソールで使用状況を可視化
  })

  // IPアドレスをidentifierとして使用
  const ip = c.req.header('CF-Connecting-IP') ?? 'anonymous'
  const { success, limit, remaining, reset } = await ratelimit.limit(ip)

  if (!success) {
    return c.json(
      { error: 'Too many requests. Please try again later.' },
      429,
      {
        'X-RateLimit-Limit': limit.toString(),
        'X-RateLimit-Remaining': remaining.toString(),
        'X-RateLimit-Reset': reset.toString(),
      }
    )
  }

  await next()
})

app.get('/api/data', (c) => {
  return c.json({ message: 'Success!' })
})

export default app

アルゴリズムの選び方

レート制限アルゴリズムは用途によって使い分けます。

  • slidingWindow(スライディングウィンドウ) — 最も滑らかな制限。一般的なAPIに最適
  • fixedWindow(固定ウィンドウ) — シンプルで軽量。ウィンドウ切り替え時に一時的に制限が緩む特性あり
  • tokenBucket(トークンバケット) — バースト許容あり。瞬間的なトラフィックスパイクを許容したい場合に有効
// ログインAPIは厳しく:1分に5回まで
const loginRatelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.fixedWindow(5, '1 m'),
})

// 一般APIは緩く:1分に60回まで
const apiRatelimit = new Ratelimit({
  redis,
  limiter: Ratelimit.slidingWindow(60, '1 m'),
})

実践3:セッション管理とフィーチャーフラグ

セッションデータの保存

JWTを使ったステートレスな認証が主流ですが、セッション失効・強制ログアウトの仕組みを作りたいときはRedisが便利です。有効なセッションIDをRedisに保存しておき、リクエストのたびに存在チェックします。

// セッション作成
async function createSession(redis: Redis, userId: string): Promise<string> {
  const sessionId = crypto.randomUUID()
  await redis.set(
    `session:${sessionId}`,
    JSON.stringify({ userId, createdAt: Date.now() }),
    { ex: 60 * 60 * 24 * 7 } // 7日間
  )
  return sessionId
}

// セッション検証
async function validateSession(redis: Redis, sessionId: string) {
  const data = await redis.get<string>(`session:${sessionId}`)
  if (!data) return null
  return JSON.parse(data)
}

// 強制ログアウト(管理者がセッションを無効化できる)
async function revokeSession(redis: Redis, sessionId: string) {
  await redis.del(`session:${sessionId}`)
}

フィーチャーフラグでリリースを安全に

新機能を特定ユーザーにだけ公開する「フィーチャーフラグ」もRedisで簡単に実装できます。コードの再デプロイなしにフラグのON/OFFができるのが強みです。

// フラグの確認
async function isFeatureEnabled(redis: Redis, feature: string, userId: string) {
  // グローバルフラグを確認
  const globalFlag = await redis.get(`feature:${feature}`)
  if (globalFlag === 'disabled') return false
  if (globalFlag === 'enabled') return true

  // ユーザー個別フラグを確認
  const userFlag = await redis.get(`feature:${feature}:user:${userId}`)
  return userFlag === 'enabled'
}

// 使用例
app.get('/api/new-ui', async (c) => {
  const redis = Redis.fromEnv(c.env)
  const 
        userId = c.get('userId')

  if (!(await isFeatureEnabled(redis, 'new-dashboard', userId))) {
    return c.json({ error: 'Feature not available' }, 403)
  }

  return c.json({ ui: 'new-dashboard-data' })
})

広告・楽天アフィリエイト

PCモニター

デュアルディスプレイや高解像度モデルをチェック。

楽天ポイント還元

モニターを楽天で見る →

広告・楽天アフィリエイト

プログラミング技術書

実践寄りの技術書・参考書を探す。

楽天ポイント還元

技術書を楽天で見る →

実践4:ランキング・スコアボードの実装

RedisのSorted Set(ソート済みセット)は、スコアボードやランキングを実装するのに特化したデータ構造です。スコアでソートされた集合を管理でき、「上位10件を取得」「特定ユーザーの順位を調べる」といった操作が高速に行えます。

// スコアを更新
await redis.zadd('leaderboard:global', {
  score: 1500,
  member: 'user:alice'
})

// 上位10位を取得(降順)
const top10 = await redis.zrange('leaderboard:global', 0, 9, {
  rev: true,
  withScores: true
})
// → [{ member: 'user:alice', score: 1500 }, ...]

// 特定ユーザーの順位を取得(0始まり)
const rank = await redis.zrevrank('leaderboard:global', 'user:alice')
console.log(`Alice is ranked #${(rank ?? 0) + 1}`)

// スコアを加算(既存スコアに追加)
await redis.zincrby('leaderboard:global', 100, 'user:alice')

このアーキテクチャは、ゲームスコア・記事いいね数ランキング・チャレンジ参加者順位など、様々なシーンで応用できます。

Upstash QStash:サーバーレスなジョブキュー

Upstashが提供するもう一つの強力なサービスが QStash です。Redisのキューとは別に、HTTPベースのジョブスケジューラーとして機能します。「30分後にメールを送る」「毎日9時にデータを集計する」といった非同期処理を、サーバーレス環境で実現できます。

npm install @upstash/qstash
import { Client } from '@upstash/qstash'

// ジョブをキューに投入
const client = new Client({ token: env.QSTASH_TOKEN })

// 5分後にメール送信エンドポイントを呼び出す
await client.publishJSON({
  url: 'https://your-worker.workers.dev/api/send-email',
  delay: '5m',
  body: {
    to: 'user@example.com',
    subject: 'ご登録ありがとうございます',
  }
})

// Cron形式でスケジュール(毎日9時)
await client.schedules.create({
  destination: 'https://your-worker.workers.dev/api/daily-report',
  cron: '0 9 * * *',
})

Cloudflare Workers単体ではCron Triggersがありますが、動的なスケジュール(ユーザーが設定した時間に実行)はQStashの方が柔軟です。

よくあるトラブルと解決方法

「connection refused」エラー

Cloudflare WorkersからUpstashへの接続に失敗する場合、@upstash/redis/cloudflare ではなく @upstash/redis を使っている可能性があります。Cloudflare Workers専用エントリーポイントをインポートしてください。

// ❌ Node.js用(Cloudflare Workersでは動かない場合がある)
import { Redis } from '@upstash/redis'

// ✅ Cloudflare Workers専用
import { Redis } from '@upstash/redis/cloudflare'

無料枠の上限に達した

Freeプランは1日10,000コマンドが上限です。redis.get()redis.set() はそれぞれ1コマンドと数えます。頻繁にアクセスされるデータには長めのTTLを設定して、リクエスト数を抑えましょう。

// TTLを長めに設定してコマ
        ンド数を削減
await redis.set('config', JSON.stringify(data), { ex: 3600 }) // 1時間
// 毎リクエストではなく、1時間に1回だけ外部APIを叩く

型安全なデータ取得

Upstash SDKはTypeScript対応ですが、get() の戻り値にジェネリクスを指定することで型安全に扱えます。

type UserData = { userId: string; name: string; plan: string }

// 型を指定して取得
const user = await redis.get<UserData>(`user:${id}`)
if (user) {
  console.log(user.name) // 型推論が効く
}

他サービスとの組み合わせ:Upstashとの最強スタック

Upstashは単体で使うよりも、他のCloudflareサービスと組み合わせるとより強力になります。

  • Hono.js + Cloudflare Workers — APIフレームワーク。UpstashをミドルウェアとしてHonoに組み込むのが定番構成
  • Cloudflare D1 — SQLiteベースのDB。永続データはD1、一時キャッシュはUpstashと使い分けると効果的
  • Cloudflare Workers + Micro SaaS — 個人開発SaaSのバックエンド全体像。Upstashはキャッシュ層として機能する

また、サービスが成長してきたら、PagePulse のような死活監視ツールでAPIの稼働状況を継続的にチェックしておくことをおすすめします。Redisへの接続が切れていないか、レスポンスタイムが正常かを自動で確認できます。

作ったサービスの稼働状況をユーザーに公開したい場合は、StatusCraft でステータスページを作成するのが手軽です。インシデント発生時の信頼性維持に役立ちます。

広告・楽天アフィリエイト

ガジェット・オーディオ

イヤホン・便利ガジェットをポイント還元で。

楽天ポイント還元

ガジェットを楽天で見る →

まとめ:Upstashで個人開発の品質を一段上げる

Upstashは「インフラ管理したくないけど、本格的なキャッシュやレート制限を実装したい」個人開発者にとって最適解の一つです。

  • 無料枠で始められる(1日10,000コマンドまで)
  • Cloudflare Workersと相性抜群(HTTP REST APIでTCP不要)
  • レート制限が5分で実装できる(@upstash/ratelimit)
  • Sorted Setでランキング機能も簡単
  • QStashでサーバーレスジョブキューも対応
  • TypeScript対応で型安全

「まずはレート制限だけ」から始めて、徐々にキャッシュ・セッション管理・ランキングと機能を追加していくのがおすすめです。Cloudflare WorkersにHono + D1 + Upstashを組み合わせたスタックは、2026年現在の個人開発バックエンドとして完成度が高く、月額コスト$0〜数ドルで本格的なWebサービスを運用できます。

ChromeでUpstashのドキュメントを読み進める際は、QuickSummary(AI要約Chrome拡張)を入れておくと、長文ドキュメントをAIで要約してくれて効率よく学習できます。

🚀 今すぐUpstashを試してみよう

クレジットカード不要で無料プランをすぐ使えます。アカウント作成〜Redis接続まで10分でできます。

Upstash公式サイトを見る →