Отметим: когда ваш сайт обслуживает пользователей по всему миру, задержка ответа становится критичной. Любой roundtrip к origin-серверу добавляет сотни миллисекунд, ухудшая LCP и TTFB. Edge Functions на Deno Deploy решают эту проблему, выполняя код на периферии — в 35+ регионах, на V8 Isolates без холодного старта, что напрямую улучшает Core Web Vitals. Мы разрабатываем такие функции под ключ: middleware, генерацию OG-изображений, кеширование, авторизацию и персонализацию на границе сети.
Наш опыт — 5+ лет в Edge-разработке, 15+ проектов под ключ. Мы гарантируем стабильность и соответствие Core Web Vitals. В отличие от Lambda или Cloud Functions, код выполняется в миллисекундах от пользователя, потому что не поднимает контейнер — изолят уже готов. Как указано в документации Deno Deploy, платформа использует V8 Isolates и не требует холодного старта. Deno Deploy docs Типичные задачи: A/B-тестирование на уровне CDN, персонализация по геолокации, middleware для авторизации, проксирование запросов с трансформацией, генерация динамических OG-изображений.
| Параметр | Edge Functions (Deno Deploy) | Cloud Functions (AWS Lambda) |
|---|---|---|
| Холодный старт | Отсутствует (изолят прогрет) | ~200 мс-1 с (контейнер) |
| География | 35+ регионов | Выбор региона при деплое |
| Языки | TypeScript нативно | Множество, но настройка слоёв |
| Встроенное хранилище | Deno KV (глобальное) | Требуется внешнее |
Как работает Deno Deploy
Каждая функция — это ES module с обработчиком Deno.serve. Платформа не поддерживает файловую систему (кроме bundle), нет setTimeout с длинными задержками, нет фонового выполнения после ответа (кроме 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 });
});
Деплой через CLI одной командой: deployctl deploy --project=my-site entry.ts.
Почему Edge Functions быстрее обычного бэкенда?
Ключевое преимущество — отсутствие холодного старта и выполнение на периферии. Запрос обрабатывается в регионе пользователя, latency снижается с 200-500 мс до 10-30 мс. Это напрямую улучшает LCP и TTFB. Кроме того, Edge-функции разгружают origin-сервер, обрабатывая кеширование и авторизацию без лишних roundtrip.
Middleware для авторизации: как устранить roundtrip к бэкенду?
Часто нужно проверить JWT до origin. На Edge это происходит без обращения к основному серверу:
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 });
}
});
Типичная ошибка — неверный импорт ключа: используйте crypto.subtle.importKey с правильным форматом.
Как интегрировать Edge-функции с существующим сайтом?
Deno Deploy работает как Edge Layer перед origin. Схема проста: DNS → Deno Deploy → Origin Server.
- Настройте DNS: направьте трафик на Deno Deploy (например, через CNAME на
deno.devили собственный домен). - Напишите функции-обработчики, которые решают: проксировать запрос на бэкенд, изменить его или ответить самостоятельно.
- Задеплойте через CLI или GitHub Actions. Менять текущий бэкенд не требуется.
Пример конфигурации deno.json
{
"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/"]
}
}
</details>
### Генерация OG-изображений на Edge
Satori — библиотека для рендеринга JSX в SVG — работает в Deno Deploy. Позволяет генерировать уникальные preview-картинки для каждой страницы без prebuild:
```typescript
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') ?? '';
const fontResponse = await fetch('https://your-cdn.com/fonts/Inter-Bold.ttf');
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',
},
});
});
Кеширование с Deno KV
Deno KV — встроенное key-value хранилище с глобальной репликацией. Используется для кеша, счётчиков, 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',
},
});
});
Что входит в разработку Edge-функций?
| Этап | Результат | Ориентировочный срок |
|---|---|---|
| Аналитика | Спецификация Edge-сценариев, выбор архитектуры | 1 день |
| Проектирование | Прототип функций, схема интеграции с origin | 1–2 дня |
| Реализация | Код, тесты, CI/CD | 2–5 дней |
| Тестирование | Нагрузочное тестирование, проверка на Edge | 1 день |
| Деплой и документация | Доступы, мониторинг, описание | 1 день |
Оставьте заявку — мы оценим ваш проект за 1 день. Напишите нам, чтобы обсудить задачи и сроки. Закажите Edge Layer под ключ с гарантией производительности.
Сроки ориентировочно
- Простая Edge-функция (редирект, геолокация, базовый middleware) — 1–2 дня.
- Middleware с JWT-верификацией и проксированием — 2–3 дня.
- Генерация OG-изображений с кешированием через Deno KV — 3–5 дней.
- Полноценный Edge Layer с rate limiting, A/B-тестированием и аналитикой — 1–2 недели.
Стоимость рассчитывается индивидуально. Получите консультацию инженера — расскажем, какие функции принесут наибольший прирост производительности.







