Cloudflare Workers for Indian Developers: Edge Computing Practical Guide

calendar_today July 21, 2026
person info@softcrony.com
folder DevOps

Cloudflare Workers lets you run JavaScript at the network edge — in data centers physically close to your users, rather than in a central server. For Indian users, this means the difference between 400ms response times from a US server and 20ms from Cloudflare’s Mumbai or Chennai edge nodes.

This guide covers what Cloudflare Workers actually is, when to use it, and how to build real things with it — specifically for Indian developers and businesses.

What Is Edge Computing?

Traditional web architecture: User in Jabalpur → Request travels to your server in Mumbai (or worse, Singapore/US) → Response travels back. Round trip: 80–400ms depending on server location.

Edge computing: User in Jabalpur → Request hits Cloudflare’s nearest node (Mumbai, ~10ms away) → Code runs at the edge → Response served immediately. Round trip: 15–30ms.

Cloudflare Workers is a serverless edge platform where your JavaScript/TypeScript code runs in Cloudflare’s network of 300+ data centers worldwide — including multiple nodes in India.

When Edge Computing Makes Sense

Use Case Edge? Why
API responses with user-specific data ✅ Yes Runs close to user, fast
Authentication/JWT validation ✅ Yes No round-trip to origin needed
A/B testing and feature flags ✅ Yes Serve different content without origin
Geolocation-based redirects ✅ Yes Cloudflare knows user location natively
Rate limiting ✅ Yes Block before reaching your server
Image transformation ✅ Yes Resize on the fly at the edge
Complex DB queries ❌ No DB is still in one location
File uploads ⚠️ Partial Route to R2, process at edge
Long-running processes ❌ No Workers have 30s CPU limit

Step 1 — Setup

npm install -g wrangler
wrangler login

# Create a new Worker project
wrangler init my-worker --type javascript
cd my-worker
// wrangler.toml
name = "softcrony-api"
main = "src/index.ts"
compatibility_date = "2026-07-01"
compatibility_flags = ["nodejs_compat"]

[vars]
ENVIRONMENT = "production"

[[kv_namespaces]]
binding = "CACHE"
id = "your-kv-namespace-id"

[[d1_databases]]
binding = "DB"
database_name = "softcrony-db"
database_id = "your-d1-database-id"

Step 2 — Basic Worker

// src/index.ts
export default {
    async fetch(request: Request, env: Env): Promise<Response> {
        const url = new URL(request.url);

        // Route based on pathname
        switch (url.pathname) {
            case '/api/health':
                return Response.json({ status: 'ok', region: request.cf?.colo });

            case '/api/geo':
                return this.handleGeo(request);

            default:
                return new Response('Not Found', { status: 404 });
        }
    },

    handleGeo(request: Request): Response {
        // Cloudflare provides geolocation data natively
        const cf = request.cf;

        return Response.json({
            country:  cf?.country,
            city:     cf?.city,
            region:   cf?.region,
            timezone: cf?.timezone,
            isp:      cf?.asOrganization,
            // Automatically detect Indian users
            isIndia:  cf?.country === 'IN',
        });
    },
};

Step 3 — Geolocation-Based Content for India

// Show prices in INR for Indian users, USD for others
export default {
    async fetch(request: Request, env: Env): Promise<Response> {
        const country = request.cf?.country;
        const isIndia = country === 'IN';

        // Fetch from origin
        const response = await fetch('https://api.softcrony.com/products');
        const products = await response.json() as Product[];

        // Transform prices based on location
        const localizedProducts = products.map(product => ({
            ...product,
            price: isIndia
                ? { amount: product.price_inr, currency: 'INR', symbol: '₹' }
                : { amount: product.price_usd, currency: 'USD', symbol: '$' },
            // Show GST info for Indian users
            tax: isIndia ? { rate: 18, label: 'GST 18%' } : null,
        }));

        return Response.json(localizedProducts, {
            headers: {
                'Cache-Control': 'public, max-age=300',
                'X-Served-From': request.cf?.colo ?? 'unknown',
                'X-User-Country': country ?? 'unknown',
            },
        });
    },
};

Step 4 — Rate Limiting at the Edge

// Rate limit before request hits your Laravel server
export default {
    async fetch(request: Request, env: Env): Promise<Response> {
        const ip = request.headers.get('CF-Connecting-IP') ?? 'unknown';
        const key = `rate_limit:${ip}`;

        // Check rate limit from KV
        const requests = parseInt(await env.CACHE.get(key) ?? '0');

        if (requests >= 100) {
            return new Response('Rate limit exceeded', {
                status: 429,
                headers: {
                    'Retry-After': '60',
                    'X-RateLimit-Limit': '100',
                    'X-RateLimit-Remaining': '0',
                },
            });
        }

        // Increment counter
        await env.CACHE.put(key, String(requests + 1), {
            expirationTtl: 60 // Reset after 60 seconds
        });

        // Pass to origin
        const response = await fetch(request);

        return new Response(response.body, {
            ...response,
            headers: {
                ...Object.fromEntries(response.headers),
                'X-RateLimit-Limit': '100',
                'X-RateLimit-Remaining': String(99 - requests),
            },
        });
    },
};

Step 5 — JWT Authentication at Edge

import { jwtVerify } from 'jose';

export default {
    async fetch(request: Request, env: Env): Promise<Response> {
        // Only protect API routes
        const url = new URL(request.url);
        if (!url.pathname.startsWith('/api/')) {
            return fetch(request);
        }

        // Skip auth for public routes
        const publicRoutes = ['/api/login', '/api/register', '/api/health'];
        if (publicRoutes.includes(url.pathname)) {
            return fetch(request);
        }

        // Validate JWT at edge — before hitting Laravel
        const authHeader = request.headers.get('Authorization');
        if (!authHeader?.startsWith('Bearer ')) {
            return Response.json({ error: 'Unauthorized' }, { status: 401 });
        }

        const token = authHeader.slice(7);

        try {
            const secret = new TextEncoder().encode(env.JWT_SECRET);
            const { payload } = await jwtVerify(token, secret);

            // Add user info to headers for Laravel
            const modifiedRequest = new Request(request, {
                headers: {
                    ...Object.fromEntries(request.headers),
                    'X-User-Id':    String(payload.sub),
                    'X-User-Email': String(payload.email),
                    'X-Tenant-Id':  String(payload.tenant_id),
                },
            });

            return fetch(modifiedRequest);

        } catch {
            return Response.json({ error: 'Invalid token' }, { status: 401 });
        }
    },
};

Step 6 — Cloudflare D1 (Edge Database)

D1 is Cloudflare’s SQLite-based edge database — query data without leaving the edge network:

// Create D1 database
wrangler d1 create softcrony-db

// Apply schema
wrangler d1 execute softcrony-db --file=./schema.sql
// schema.sql
CREATE TABLE products (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    price_inr INTEGER NOT NULL,
    price_usd INTEGER NOT NULL,
    status TEXT DEFAULT 'active',
    created_at TEXT DEFAULT (datetime('now'))
);
// Query D1 from Worker
export default {
    async fetch(request: Request, env: Env): Promise<Response> {
        const { results } = await env.DB.prepare(
            'SELECT * FROM products WHERE status = ? ORDER BY created_at DESC LIMIT 20'
        )
        .bind('active')
        .all();

        return Response.json(results);
    },
};

Step 7 — Deploy

# Deploy to production
wrangler deploy

# Test locally first
wrangler dev

# View logs in real time
wrangler tail

Performance Impact for Indian Users

Real numbers from a client project — a product listing API moved from a DigitalOcean server in Singapore to Cloudflare Workers:

Location Before (Singapore) After (Edge) Improvement
Mumbai 180ms 18ms 90% faster
Delhi 210ms 22ms 90% faster
Jabalpur 240ms 25ms 90% faster
Chennai 160ms 15ms 91% faster
Kolkata 230ms 28ms 88% faster

For the right use cases — API responses, authentication, rate limiting, geolocation — edge computing delivers 10x latency improvements for Indian users. This directly impacts conversion rates and user experience on mobile networks.

If you want to implement Cloudflare Workers for your application or need edge computing architecture for an Indian-market product, our team at Softcrony can design and implement it.

Leave a comment