Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

分散設定ストアを構築する

Workers KV を、Workers アプリケーション向けの地理分散した低レイテンシの設定ストアとして使います

最終更新 Markdown で表示Agent セットアップ

Workers KV は、アプリケーションの設定データを保存するのに適しています。設定データには、ユーザーやテナントごとにアプリケーションをパーソナライズするデータ、ユーザーグループ向けの機能の有効化、許可リスト / 拒否リストによるアクセス制限などが含まれます。こうしたユースケースは読み取り量が多く、Workers KV で高いキャッシュ効率を得やすいため、Workers アプリケーションから低レイテンシで読み取れます。

この例では、アプリケーションの設定データを使って、ユーザーごとに Workers アプリケーションをパーソナライズします。設定データは外部アプリケーションとデータベースに保存し、REST API で Workers KV へ書き込みます。

外部アプリケーションから Workers KV へ設定を書き込む

設定データの信頼できる情報源(source of truth)が Workers KV 以外にある場合があります。その場合は、Workers KV REST API を使って、設定データを Workers KV 名前空間へ書き込みます。

次の外部 Node.js アプリケーションは、データベースからユーザーデータを読み取り、REST API ライブラリで Workers KV へ書き込む簡単なスクリプトです。

index.jsjs
const postgres = require('postgres');
const { Cloudflare } = require('cloudflare');
const { backOff } = require('exponential-backoff');

if(!process.env.DATABASE_CONNECTION_STRING || !process.env.CLOUDFLARE_EMAIL || !process.env.CLOUDFLARE_API_KEY || !process.env.CLOUDFLARE_WORKERS_KV_NAMESPACE_ID || !process.env.CLOUDFLARE_ACCOUNT_ID) {
console.error('Missing required environment variables.');
process.exit(1);
}

// Setup Postgres connection
const sql = postgres(process.env.DATABASE_CONNECTION_STRING);

// Setup Cloudflare REST API client
const client = new Cloudflare({
apiEmail: process.env.CLOUDFLARE_EMAIL,
apiKey: process.env.CLOUDFLARE_API_KEY,
});

// Function to sync Postgres data to Workers KV
async function syncPreviewStatus() {
console.log('Starting sync of user preview status...');

    try {
    	// Get all users and their preview status
    	const users = await sql`SELECT id, preview_features_enabled FROM users`;

    	console.log(users);

    	// Create the bulk update body
    	const bulkUpdateBody = users.map(user => ({
    		key: user.id,
    		value: JSON.stringify({
    			preview_features_enabled: user.preview_features_enabled
    		})
    	}));

    	const response = await backOff(async () => {
    		console.log("trying to update")
    		try{
    			const response = await client.kv.namespaces.bulkUpdate(process.env.CLOUDFLARE_WORKERS_KV_NAMESPACE_ID, {
    				account_id: process.env.CLOUDFLARE_ACCOUNT_ID,
    				body: bulkUpdateBody
    			});
    		}
    		catch(e){
    			// Implement your error handling and logging here
    			console.log(e);
    			throw e; // Rethrow the error to retry
    		}
    	});

    	console.log(`Sync complete. Updated ${users.length} users.`);
    } catch (error) {
    	console.error('Error syncing preview status:', error);
    }

}

// Run the sync function
syncPreviewStatus()
.catch(console.error)
.finally(() => process.exit(0));
.envmd
DATABASE_CONNECTION_STRING = <DB_CONNECTION_STRING_HERE>
CLOUDFLARE_EMAIL = <CLOUDFLARE_EMAIL_HERE>
CLOUDFLARE_API_KEY = <CLOUDFLARE_API_KEY_HERE>
CLOUDFLARE_ACCOUNT_ID = <CLOUDFLARE_ACCOUNT_ID_HERE>
CLOUDFLARE_WORKERS_KV_NAMESPACE_ID = <CLOUDFLARE_WORKERS_KV_NAMESPACE_ID_HERE>
db.sqlsql
-- Create users table with preview_features_enabled flag
CREATE TABLE users (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  username VARCHAR(100) NOT NULL,
  email VARCHAR(255) NOT NULL,
  preview_features_enabled BOOLEAN DEFAULT false
);

-- Insert sample users
INSERT INTO users (username, email, preview_features_enabled) VALUES
('alice', '[email protected]', true),
('bob', '[email protected]', false),
('charlie', '[email protected]', true);

このコードでは、Node.js アプリケーションが Postgres データベースからユーザーデータを読み取り、Workers アプリケーションの設定として使うユーザーデータを、Cloudflare REST API の Node.js ライブラリで Workers KV へ書き込みます。エラー時の再試行には exponential backoff を使います。

Worker アプリケーションで Workers KV の設定データを使う

設定データが Workers KV 名前空間に入ったので、Workers アプリケーションでユーザーごとにパーソナライズできます。

index.tsjs
// Example configuration data stored in Workers KV:
// Key: "user-id-abc" | Value: {"preview_features_enabled": false}
// Key: "user-id-def" | Value: {"preview_features_enabled": true}

interface Env {
  USER_CONFIGURATION: KVNamespace;
}

export default {
  async fetch(request, env) {
    // Get user ID from query parameter
    const url = new URL(request.url);
    const userId = url.searchParams.get('userId');

    if (!userId) {
      return new Response('Please provide a userId query parameter', {
        status: 400,
        headers: { 'Content-Type': 'text/plain' }
      });
    }


		const userConfiguration = await env.USER_CONFIGURATION.get<{
			preview_features_enabled: boolean;
		}>(userId, {type: "json"});

		console.log(userConfiguration);

    // Build HTML response
    const html = `
      <!DOCTYPE html>
      <html>
        <head>
          <title>My App</title>
          <style>
            body {
              font-family: Arial, sans-serif;
              max-width: 800px;
              margin: 0 auto;
              padding: 20px;
            }
            .preview-banner {
              background-color: #ffeb3b;
              padding: 10px;
              text-align: center;
              margin-bottom: 20px;
              border-radius: 4px;
            }
          </style>
        </head>
        <body>
          ${userConfiguration?.preview_features_enabled ? `
            <div class="preview-banner">
              🎉 You have early access to preview features! 🎉
            </div>
          ` : ''}
          <h1>Welcome to My App</h1>
          <p>This is the regular content everyone sees.</p>
        </body>
      </html>
    `;

    return new Response(html, {
			headers: { "Content-Type": "text/html; charset=utf-8" }
    });
  }
} satisfies ExportedHandler<Env>;
{
	"$schema": "node_modules/wrangler/config-schema.json",
	"name": "<ENTER_WORKER_NAME>",
	"main": "src/index.ts",
	"compatibility_date": "2025-03-03",
	"observability": {
		"enabled": true
	},
	"kv_namespaces": [
		{
			"binding": "USER_CONFIGURATION",
			"id": "<YOUR_BINDING_ID>"
		}
	]
}

このコードは、URL 内のパスを使い、KV ストア内でそのパスに対応するファイルを探します。レスポンスには適切な MIME タイプを設定し、ブラウザーがレスポンスをどう扱うかを伝えます。KV ストアから値を取得するとき、このコードは arrayBuffer を使い、画像、ドキュメント、動画 / 音声ファイルなどのバイナリデータを正しく扱います。

設定のパフォーマンスを最適化する

パフォーマンスを最適化するには、より少ないキーと値のペアに値をまとめる方法があります。キャッシュ効率が上がり、レイテンシが下がることがあります。

たとえば、ユーザーごとの設定を別々のキーと値のペアに保存する代わりに、全ユーザーの設定を 1 つのキーと値のペアにまとめて保存できます。設定データが小さく、1 つのキーと値のペアで管理しやすい場合に向いています(Workers KV の値のサイズ上限は 25 MiB です)。

関連リソース

役に立ちましたか?