Implement Edge Middleware and Serverless Functions on Deno Deploy
When your site serves users across the globe, latency becomes critical. Each roundtrip to the origin server adds hundreds of milliseconds, worsening LCP and TTFB. Edge Functions on Deno Deploy solve this by executing code at the periphery — in 35+ regions, on V8 Isolates with no cold start, directly improving Core Web Vitals. We build these functions turnkey: middleware, OG image generation, caching, authorization, and personalization at the network edge.
Our experience: 5+ years in edge development, 15+ turnkey projects. We guarantee stability and Core Web Vitals compliance. Unlike Lambda or Cloud Functions, code runs within milliseconds of the user because no container is spun up — the isolate is already warm. As documented by Deno Deploy docs, the platform uses V8 Isolates and eliminates cold starts.
Typical Tasks We Solve
- A/B testing at the CDN level
- Geo-location personalization
- Authorization middleware
- Request proxying with transformation
- Dynamic OG image generation
Comparison: Edge Functions vs Cloud Functions
| Parameter | Edge Functions (Deno Deploy) | Cloud Functions (AWS Lambda) |
|---|---|---|
| Cold start | None (isolate pre-warmed) | ~200 ms–1 s (container) |
| Geography | 35+ regions | Region selection at deploy |
| Languages | TypeScript natively | Multiple, but layer configuration |
| Built-in storage | Deno KV (global) | External required |
Deno Deploy is up to 10x faster than AWS Lambda due to no cold starts and execution at the edge.
How Deno Deploy Works
Each function is an ES module with a Deno.serve handler. The platform does not support the file system (except bundle), no long setTimeout, and no background execution after response (except waitUntil).
// entry.ts
Deno.serve(async (req: Request) => {
const url = new URL(req.url);
if (url.pathname === '/api/geo') {
const country = req.headers.get('x-deno-country') ?? 'unknown';
const region = req.headers.get('x-deno-region') ?? 'unknown';
return Response.json({ country, region });
}
return new Response('Not Found', { status: 404 });
});
Deploy via CLI with one command: deployctl deploy --project=my-site entry.ts.
Why Edge Functions Outperform Traditional Backends
The key advantage is no cold start and execution at the edge. Requests are handled in the user's region, reducing latency from 200–500 ms to 10–30 ms — improving LCP by up to 40%. This directly improves Core Web Vitals. Additionally, edge functions offload the origin server by handling caching and authorization without extra roundtrips.
Case: JWT Authentication Middleware
Often you need to verify a JWT before hitting the origin. On the edge, this happens without contacting the main server:
import { create, verify, getNumericDate } from 'https://deno.land/x/[email protected]/mod.ts';
const JWT_SECRET = Deno.env.get('JWT_SECRET')!;
async function getKey(secret: string): Promise<CryptoKey> {
const enc = new TextEncoder();
return await crypto.subtle.importKey(
'raw',
enc.encode(secret),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign', 'verify']
);
}
Deno.serve(async (req: Request) => {
const url = new URL(req.url);
if (url.pathname.startsWith('/public') || url.pathname === '/') {
return await fetch(req);
}
const authHeader = req.headers.get('Authorization');
if (!authHeader?.startsWith('Bearer ')) {
return new Response('Unauthorized', { status: 401 });
}
const token = authHeader.slice(7);
try {
const key = await getKey(JWT_SECRET);
const payload = await verify(token, key);
const modifiedReq = new Request(req, {
headers: {
...Object.fromEntries(req.headers),
'x-user-id': String(payload.sub),
'x-user-role': String(payload.role ?? 'user'),
},
});
return await fetch(modifiedReq);
} catch {
return new Response('Invalid token', { status: 401 });
}
});
A common mistake is incorrect key import — use crypto.subtle.importKey with the correct format.
Integrating Edge Functions with Your Existing Site
Deno Deploy works as an Edge Layer before the origin. The flow is simple: DNS → Deno Deploy → Origin Server.
- Configure DNS: point traffic to Deno Deploy (e.g., via CNAME to
deno.devor your own domain). - Write handler functions that decide whether to proxy to the backend, modify the request, or respond directly.
- Deploy via CLI or GitHub Actions. No changes to your current backend are required.
Example deno.json configuration
{
"tasks": {
"dev": "deno run --allow-net --allow-env --watch entry.ts",
"deploy": "deployctl deploy --project=my-site --prod entry.ts"
},
"imports": {
"djwt": "https://deno.land/x/[email protected]/mod.ts"
},
"deploy": {
"project": "my-site",
"entrypoint": "entry.ts",
"include": ["entry.ts", "lib/"]
}
}
Case: OG Image Generation on the Edge
Satori — a library for rendering JSX to SVG — works in Deno Deploy. It generates unique preview images per page without prebuilding:
import satori from 'npm:[email protected]';
import { Resvg } from 'npm:@resvg/[email protected]';
Deno.serve(async (req: Request) => {
const url = new URL(req.url);
if (!url.pathname.startsWith('/og')) return new Response('Not Found', { status: 404 });
const title = url.searchParams.get('title') ?? 'My Site';
const description = url.searchParams.get('desc') ?? '';
// Fetch the font from CDN (e.g., Inter-Bold)
const fontResponse = await fetch('https://unpkg.com/@fontsource/[email protected]/files/inter-latin-700-normal.woff');
const fontBuffer = await fontResponse.arrayBuffer();
const svg = await satori(
{
type: 'div',
props: {
style: {
display: 'flex',
flexDirection: 'column',
width: '100%',
height: '100%',
background: '#0f172a',
padding: '60px',
fontFamily: 'Inter',
},
children: [
{
type: 'h1',
props: {
style: { color: '#f8fafc', fontSize: 56, margin: 0, lineHeight: 1.2 },
children: title,
},
},
{
type: 'p',
props: {
style: { color: '#94a3b8', fontSize: 28, marginTop: 24 },
children: description,
},
},
],
},
},
{
width: 1200,
height: 630,
fonts: [{ name: 'Inter', data: fontBuffer, weight: 700, style: 'normal' }],
}
);
const resvg = new Resvg(svg);
const png = resvg.render().asPng();
return new Response(png, {
headers: {
'Content-Type': 'image/png',
'Cache-Control': 'public, max-age=86400, stale-while-revalidate=604800',
},
});
});
Case: Caching with Deno KV
Deno KV is a built-in key-value store with global replication. Useful for caching, counters, rate limiting:
const kv = await Deno.openKv();
Deno.serve(async (req: Request) => {
const url = new URL(req.url);
const cacheKey = ['cache', url.pathname + url.search];
const cached = await kv.get<string>(cacheKey);
if (cached.value) {
return new Response(cached.value, {
headers: {
'Content-Type': 'application/json',
'X-Cache': 'HIT',
},
});
}
const response = await fetch(`https://api.example.com${url.pathname}`);
const data = await response.text();
await kv.set(cacheKey, data, { expireIn: 5 * 60 * 1000 });
return new Response(data, {
headers: {
'Content-Type': 'application/json',
'X-Cache': 'MISS',
},
});
});
What's Included in the Work
- Analysis of edge scenarios and architecture selection
- Development of functions with tests and CI/CD
- Documentation of deployed functions and integration details
- Access to monitoring and logs
- Post-deployment support for 30 days
- Training session for your team (up to 2 hours)
Our Development Process
| Stage | Outcome | Estimated Time |
|---|---|---|
| Analysis | Specification of edge scenarios, architecture selection | 1 day |
| Design | Function prototypes, integration scheme with origin | 1–2 days |
| Implementation | Code, tests, CI/CD | 2–5 days |
| Testing | Load testing, edge validation | 1 day |
| Deployment & Documentation | Access, monitoring, description | 1 day |
With over 5 years of experience and 15+ completed projects, we have a proven track record. Leave a request — we will evaluate your project within 1 day. Contact us to discuss tasks and timelines. Order an Edge Layer turnkey with performance guarantee.
Estimated Timelines and Investment
- Simple Edge Function (redirect, geolocation, basic middleware): 1–2 days, from $500.
- Middleware with JWT verification and proxying: 2–3 days, from $1,500.
- OG image generation with caching via Deno KV: 3–5 days, from $2,500.
- Full Edge Layer with rate limiting, A/B testing, analytics: 1–2 weeks, from $5,000.
Cost is calculated individually. Get a consultation from an engineer — we'll tell you which functions will bring the most performance gain.







