How to Send OTP with Cloudflare Workers (2026)
Cloudflare Workers OTP tutorial using StartMessaging. Uses Workers fetch, KV for rate-limit, signed-cookie session, and Durable Objects for production-grade pumping defence.
StartMessaging Team
Engineering
Cloudflare Workers gives you a global, sub-millisecond edge for OTP login. This tutorial uses Hono-on-Workers + KV / Durable Objects for rate limiting.
Setup
pnpm create cloudflare otp-worker
cd otp-worker && pnpm install honoWrangler Config
# wrangler.toml
name = "otp-worker"
main = "src/index.ts"
compatibility_date = "2026-04-01"
[[kv_namespaces]]
binding = "RATE_LIMIT_KV"
id = "<your-kv-id>"
# secrets via: wrangler secret put SM_API_KEYThe Worker
// src/index.ts
import { Hono } from 'hono';
type Env = { Bindings: { SM_API_KEY: string; RATE_LIMIT_KV: KVNamespace }};
const app = new Hono<Env>();
app.post('/auth/send-otp', async (c) => {
const { phoneNumber } = await c.req.json();
// simple per-phone hour cap
const key = `rl:${phoneNumber}`;
const count = parseInt((await c.env.RATE_LIMIT_KV.get(key)) ?? '0');
if (count >= 5) return c.json({ error: 'rate limited' }, 429);
await c.env.RATE_LIMIT_KV.put(key, String(count + 1), { expirationTtl: 3600 });
const r = await fetch('https://api.startmessaging.com/otp/send', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'X-API-Key': c.env.SM_API_KEY },
body: JSON.stringify({ phoneNumber, idempotencyKey: crypto.randomUUID() }),
});
if (!r.ok) return c.json({ error: 'upstream' }, 502);
return c.json((await r.json<any>()).data);
});
export default app;Rate Limiting via KV
KV is good enough for soft per-phone caps where eventual consistency is acceptable. For hard limits switch to Durable Objects.
Per-Phone Limits via Durable Objects
Use a Durable Object per phone-number; it serialises increments and gives you exact-once limit enforcement.
Deploy
wrangler secret put SM_API_KEY
wrangler deployFAQ
For full rate-limit patterns see our OTP rate-limiting guide.
Related Articles
Hono OTP tutorial using StartMessaging. Targets Cloudflare Workers, Bun and Node. Uses zValidator, JSON schema, signed-cookie session and middleware-based rate limiting.
Bun OTP tutorial using StartMessaging. Uses Bun.serve, Bun.password.hash for credential hygiene, native fetch and zero npm install required.
Deno OTP tutorial using StartMessaging. Uses Deno.serve, native fetch, signed-cookie helpers and runs on Deno Deploy with zero infrastructure.
Ready to Send OTPs?
Integrate StartMessaging in 5 minutes. No DLT registration required.