Workers KV は、アプリケーションの設定データを保存するのに適しています。設定データには、ユーザーやテナントごとにアプリケーションをパーソナライズするデータ、ユーザーグループ向けの機能の有効化、許可リスト / 拒否リストによるアクセス制限などが含まれます。こうしたユースケースは読み取り量が多く、Workers KV で高いキャッシュ効率を得やすいため、Workers アプリケーションから低レイテンシで読み取れます。
この例では、アプリケーションの設定データを使って、ユーザーごとに Workers アプリケーションをパーソナライズします。設定データは外部アプリケーションとデータベースに保存し、REST API で Workers KV へ書き込みます。
設定データの信頼できる情報源(source of truth)が Workers KV 以外にある場合があります。その場合は、Workers KV REST API を使って、設定データを Workers KV 名前空間へ書き込みます。
次の外部 Node.js アプリケーションは、データベースからユーザーデータを読み取り、REST API ライブラリで Workers KV へ書き込む簡単なスクリプトです。
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));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>-- 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 を使います。
設定データが Workers KV 名前空間に入ったので、Workers アプリケーションでユーザーごとにパーソナライズできます。
// 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 です)。