Skip to content
API ReferenceZilliz CloudMilvusAttu

Deploying to Cloudflare Workers

This guide covers deploying the Milvus Node.js SDK to Cloudflare Workers using the HTTP client.

Cloudflare Workers only support HTTP/HTTPS protocols and do not support raw TCP connections required by gRPC. Therefore, you must use the HttpClient when deploying to Cloudflare Workers.

  • A Cloudflare account
  • Wrangler CLI installed: npm install -g wrangler
  • A Milvus instance (self-hosted or Zilliz Cloud)

Install the SDK in your Cloudflare Workers project:

Terminal window
npm install @zilliz/milvus2-sdk-node
# or
yarn add @zilliz/milvus2-sdk-node

Create src/index.js (or worker.js):

import { HttpClient } from '@zilliz/milvus2-sdk-node';
export default {
async fetch(request, env, ctx) {
const client = new HttpClient({
baseURL: env.MILVUS_ENDPOINT,
token: env.MILVUS_TOKEN,
timeout: 25000, // Cloudflare Workers free tier: 30s, paid: up to 15min
});
try {
const url = new URL(request.url);
const path = url.pathname;
// Handle different endpoints
if (path === '/search' && request.method === 'POST') {
const body = await request.json();
const results = await client.search({
collectionName: body.collectionName || 'my_collection',
data: body.vectors,
limit: body.limit || 10,
outputFields: body.outputFields || [],
});
return new Response(JSON.stringify({ results }), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
});
}
if (path === '/insert' && request.method === 'POST') {
const body = await request.json();
const result = await client.insert({
collectionName: body.collectionName || 'my_collection',
data: body.data,
});
return new Response(JSON.stringify({ result }), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
});
}
return new Response('Not Found', { status: 404 });
} catch (error) {
console.error('Milvus error:', error);
return new Response(
JSON.stringify({
error: error.message,
status: error.status || 500,
}),
{
status: error.status || 500,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
}
);
}
},
};

Create wrangler.toml:

name = "milvus-worker"
main = "src/index.js"
compatibility_date = "2024-01-01"
# Environment variables (use secrets for production)
[vars]
# MILVUS_ENDPOINT = "https://your-instance.zillizcloud.com"
# MILVUS_TOKEN = "your-token"
# For production, use secrets instead:
# wrangler secret put MILVUS_ENDPOINT
# wrangler secret put MILVUS_TOKEN
# Worker limits
[limits]
cpu_ms = 50 # CPU time limit in milliseconds

For production, use Wrangler secrets instead of environment variables:

Terminal window
wrangler secret put MILVUS_ENDPOINT
# Enter: https://your-instance.zillizcloud.com
wrangler secret put MILVUS_TOKEN
# Enter: your-api-token

For better performance, reuse the client instance within the same request context:

import { HttpClient } from '@zilliz/milvus2-sdk-node';
let clientCache = null;
function getClient(env) {
if (!clientCache) {
clientCache = new HttpClient({
baseURL: env.MILVUS_ENDPOINT,
token: env.MILVUS_TOKEN,
timeout: 25000,
});
}
return clientCache;
}
export default {
async fetch(request, env, ctx) {
const client = getClient(env);
// ... rest of your code
},
};

Here’s a complete example for a vector search API:

import { HttpClient } from '@zilliz/milvus2-sdk-node';
export default {
async fetch(request, env) {
// Handle CORS preflight
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
});
}
const client = new HttpClient({
baseURL: env.MILVUS_ENDPOINT,
token: env.MILVUS_TOKEN,
timeout: 25000,
});
try {
const url = new URL(request.url);
if (url.pathname === '/api/search' && request.method === 'POST') {
const body = await request.json();
if (!body.vector || !body.collectionName) {
return new Response(
JSON.stringify({ error: 'Missing required fields' }),
{
status: 400,
headers: { 'Content-Type': 'application/json' },
}
);
}
const results = await client.search({
collectionName: body.collectionName,
data: [body.vector],
limit: body.limit || 10,
outputFields: body.outputFields || [],
searchParams: body.searchParams || {},
});
return new Response(JSON.stringify({ results }), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
});
}
return new Response('Not Found', { status: 404 });
} catch (error) {
console.error('Error:', error);
return new Response(
JSON.stringify({
error: error.message,
status: error.status || 500,
}),
{
status: error.status || 500,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
}
);
}
},
};
Terminal window
# Login to Cloudflare
wrangler login
# Deploy
wrangler deploy
# Deploy to a specific environment
wrangler deploy --env production
Terminal window
# Start local development server
wrangler dev
# Test with curl
curl -X POST http://localhost:8787/api/search \
-H "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"vector": [0.1, 0.2, 0.3],
"limit": 5
}'
  • Free tier: 30 seconds CPU time, 30 seconds wall-clock time
  • Paid tier: Up to 15 minutes CPU time, 30 seconds wall-clock time (can be extended)

Set your timeout accordingly:

const client = new HttpClient({
baseURL: env.MILVUS_ENDPOINT,
token: env.MILVUS_TOKEN,
timeout: 25000, // Leave buffer for Worker overhead
});
  1. Use HTTP Client: Cloudflare Workers only support HTTP/HTTPS, not gRPC
  2. Set appropriate timeouts: Account for Worker execution limits
  3. Handle errors gracefully: Return proper HTTP status codes
  4. Use secrets for credentials: Never commit tokens to your repository
  5. Enable CORS: If calling from browser, set appropriate CORS headers
  6. Client reuse: Reuse client instances within the same request context
  7. Monitor performance: Use Cloudflare Analytics to track execution times

Solution: Use HttpClient instead of MilvusClient.

Solution:

  • Reduce timeout value to leave buffer for Worker overhead
  • Optimize your Milvus queries
  • Consider upgrading to paid tier for longer execution times

Solution: Ensure @zilliz/milvus2-sdk-node is installed and listed in package.json.