Deploying to Cloudflare Workers
This guide covers deploying the Milvus Node.js SDK to Cloudflare Workers using the HTTP client.
Why HTTP Client for Cloudflare Workers?
Section titled “Why HTTP Client for Cloudflare Workers?”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.
Prerequisites
Section titled “Prerequisites”- A Cloudflare account
- Wrangler CLI installed:
npm install -g wrangler - A Milvus instance (self-hosted or Zilliz Cloud)
Installation
Section titled “Installation”Install the SDK in your Cloudflare Workers project:
npm install @zilliz/milvus2-sdk-node# oryarn add @zilliz/milvus2-sdk-nodeBasic Setup
Section titled “Basic Setup”1. Create Worker File
Section titled “1. Create Worker File”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({ collection_name: body.collection_name || 'my_collection', data: body.vectors, limit: body.limit || 10, output_fields: body.output_fields || [], });
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({ collection_name: body.collection_name || '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': '*', }, } ); } },};2. Configure Wrangler
Section titled “2. Configure Wrangler”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 milliseconds3. Set Secrets (Production)
Section titled “3. Set Secrets (Production)”For production, use Wrangler secrets instead of environment variables:
wrangler secret put MILVUS_ENDPOINT# Enter: https://your-instance.zillizcloud.com
wrangler secret put MILVUS_TOKEN# Enter: your-api-tokenAdvanced Example: Client Reuse
Section titled “Advanced Example: Client Reuse”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 },};Complete Example: Vector Search API
Section titled “Complete Example: Vector Search API”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.collection_name) { return new Response( JSON.stringify({ error: 'Missing required fields' }), { status: 400, headers: { 'Content-Type': 'application/json' }, } ); }
const results = await client.search({ collection_name: body.collection_name, data: [body.vector], limit: body.limit || 10, output_fields: body.output_fields || [], search_params: body.search_params || {}, });
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': '*', }, } ); } },};Deployment
Section titled “Deployment”Deploy to Cloudflare Workers
Section titled “Deploy to Cloudflare Workers”# Login to Cloudflarewrangler login
# Deploywrangler deploy
# Deploy to a specific environmentwrangler deploy --env productionTest Locally
Section titled “Test Locally”# Start local development serverwrangler dev
# Test with curlcurl -X POST http://localhost:8787/api/search \ -H "Content-Type: application/json" \ -d '{ "collection_name": "my_collection", "vector": [0.1, 0.2, 0.3], "limit": 5 }'Timeout Limits
Section titled “Timeout Limits”- 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});Best Practices
Section titled “Best Practices”- Use HTTP Client: Cloudflare Workers only support HTTP/HTTPS, not gRPC
- Set appropriate timeouts: Account for Worker execution limits
- Handle errors gracefully: Return proper HTTP status codes
- Use secrets for credentials: Never commit tokens to your repository
- Enable CORS: If calling from browser, set appropriate CORS headers
- Client reuse: Reuse client instances within the same request context
- Monitor performance: Use Cloudflare Analytics to track execution times
Troubleshooting
Section titled “Troubleshooting”Error: “gRPC is not supported”
Section titled “Error: “gRPC is not supported””Solution: Use HttpClient instead of MilvusClient.
Error: “Request timeout”
Section titled “Error: “Request timeout””Solution:
- Reduce timeout value to leave buffer for Worker overhead
- Optimize your Milvus queries
- Consider upgrading to paid tier for longer execution times
Error: “Module not found”
Section titled “Error: “Module not found””Solution: Ensure @zilliz/milvus2-sdk-node is installed and listed in package.json.
Next Steps
Section titled “Next Steps”- Learn about Vercel Deployment
- Explore AWS Lambda Deployment
- Check out HTTP Client Guide
- Read Best Practices