Перейти к содержимому

API Gateway, BFF и Service Mesh

Зачем знать: Между клиентом и микросервисами есть слой, который занимается auth, rate limiting, routing, transformation. Это API Gateway или BFF. И между микросервисами есть service mesh — инфраструктурный слой для secure observable communication. Middle Go-разработчик должен понимать разницу между Kong, KrakenD, Envoy и собственным gateway на chi/gin, знать когда BFF (Backend for Frontend) оправдан, и когда service mesh не overkill.

  1. Концепция: API Gateway, BFF, Service Mesh
  2. Реализации: Kong, KrakenD, custom Go, Istio, Linkerd, GraphQL
  3. Gotchas
  4. Real cases
  5. Вопросы (20)
  6. Practice
  7. Источники

API Gateway — single entry point для backend services. Все запросы извне идут через него.

┌─── /users ──→ User Service
[Client] → [Gateway] ──── /orders ──→ Order Service
└─── /payments → Payment Service

Функции:

  1. Routing — направить запрос к нужному сервису по path/method/headers.
  2. Authentication / Authorization — проверка JWT, OAuth2, API keys. Централизованно.
  3. Rate limiting — ограничение QPS per client/API key.
  4. Request/response transformation — добавить/удалить headers, переписать body, версионирование.
  5. Aggregation — соединить ответы от нескольких сервисов в один.
  6. Caching — кэширование GET ответов.
  7. Compression — gzip/brotli.
  8. TLS termination — расшифровка HTTPS, дальше plain HTTP внутри VPC.
  9. Observability — единая точка для метрик, трейсов, логов.
  10. Protocol translation — gRPC ↔ REST, WebSocket ↔ HTTP.

Why не client → service directly?

  • Клиент не должен знать топологию сервисов.
  • Auth и rate limit нужны на каждом сервисе → дубликация.
  • CORS, CSP, security headers — лучше централизованно.
  • North-south traffic: между клиентом (browser, mobile) и сервисами. Gateway работает здесь.
  • East-west traffic: между микросервисами внутри cluster. Service mesh работает здесь.
  • Edge gateway: на границе сети, ближе всех к клиенту.
  • Internal gateway: между сервисами разных bounded contexts.

⚠️ Business logic в gateway. Gateway должен быть тонким. Если он считает скидки, валидирует бизнес-правила — это уже сервис, не gateway. Сложно тестировать, дебажить, масштабировать.

⚠️ Шлюз как монолит. Один gateway для 50 микросервисов с сотнями routes — single point of failure и развёртывание становится медленным. Можно дробить на несколько gateways по доменам.

⚠️ Долгие операции в gateway. Timeout gateway = upper bound для всех запросов. Если есть долгие операции (export, video processing) — должны идти через async pattern, не через gateway.

⚠️ State в gateway. Gateway должен быть stateless (rate limit state — внешне, в Redis). Иначе scaling сложен.

Pattern: gateway проверяет JWT, передаёт user info в headers вниз.

[Client]
Authorization: Bearer eyJ...
[Gateway]
- Validate JWT signature
- Check expiration
- Extract user_id, roles
[Service]
X-User-ID: 42
X-User-Roles: admin,user

Pros: сервисы не валидируют JWT (быстрее). Доверие headers внутри сети.

⚠️ Защита: убедись, что эти headers нельзя послать клиентом напрямую. Gateway должен зачищать X-User-* из входящих и устанавливать сам.

JWKS rotation: при ротации ключей у IdP gateway периодически обновляет JWKS. Не хардкодить ключ.

Алгоритмы:

  • Fixed window: сбрасывается каждую минуту. Spike на границе окна (2 минуты — двойной burst).
  • Sliding window: скользящее окно (log запросов). Точнее, но дороже по памяти.
  • Token bucket: burst-friendly. Используется в golang.org/x/time/rate.
  • Leaky bucket: стабильный rate, без burst.

Storage:

  • Redis для distributed (несколько gateway instances).
  • In-memory только для single instance.

Keys:

  • Per IP (для DDoS protection).
  • Per API key (для quotas customer’ов).
  • Per endpoint (защита тяжёлого endpoint).
  • Per user (для logged-in).

Pattern (Sam Newman, ThoughtWorks 2015): каждый frontend (mobile, web, partner API) имеет свой backend. Не один API на всех.

[iOS app] → [BFF iOS]
[Web app] → [BFF Web] ──→ [Microservices...]
[Partners] → [BFF Partner]

Зачем:

  • Mobile хочет минимум данных (battery, network) → BFF aggregates, returns compact JSON.
  • Web хочет богатые данные с relationships → BFF делает joins.
  • Partners хотят stable contract → BFF изолирует от внутренних изменений.

Преимущества:

  • Each BFF владеет своей frontend-командой.
  • Backwards compatibility per client.
  • Aggregation reduces round-trips (N+1 problem mobile).

Trade-offs:

  • Больше сервисов = больше maintenance.
  • Дублирование логики (несколько BFF делают похожие вещи).

Когда BFF не нужен: небольшая команда, один frontend → один API достаточно.

BFF может агрегировать данные из нескольких сервисов:

func (b *BFF) GetOrderDetails(ctx context.Context, orderID string) (OrderDetails, error) {
var order Order
var customer Customer
var items []Item
g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
var err error
order, err = b.orderService.Get(ctx, orderID)
return err
})
g.Go(func() error {
var err error
items, err = b.itemService.List(ctx, orderID)
return err
})
if err := g.Wait(); err != nil {
return OrderDetails{}, err
}
// customer зависит от order
customer, err := b.customerService.Get(ctx, order.CustomerID)
if err != nil {
return OrderDetails{}, err
}
return OrderDetails{Order: order, Customer: customer, Items: items}, nil
}

Параллельные вызовы через errgroup снижают latency.

GraphQL хорошо подходит для BFF: клиент сам выбирает поля и связи.

query {
order(id: "123") {
id
total
customer {
name
email
}
items {
title
price
}
}
}

Один запрос → BFF делает 3 вызова к microservices → возвращает структуру.

Service Mesh = инфраструктурный слой для service-to-service связи. Решает проблемы:

  • Service discovery.
  • Load balancing.
  • Encryption (mTLS).
  • Retries, timeouts, circuit breaking.
  • Observability (metrics, tracing, logging).
  • Traffic management (canary, A/B, blue-green).

Архитектура: sidecar pattern — у каждого pod’а есть второй контейнер (proxy, обычно Envoy). Весь сетевой трафик идёт через proxy.

[Pod]
├── [App container]
│ ↕ localhost
├── [Envoy sidecar]
│ ↕ network
[Pod]
├── [Envoy sidecar]
│ ↕ localhost
├── [App container]

Control plane (Istio, Linkerd) программирует sidecars через xDS API.

Преимущества:

  • Язык-агностично (не нужны клиенты в каждом языке).
  • Observability “из коробки”.
  • mTLS прозрачно.
  • Traffic management без изменения кода.

Недостатки:

  • Resource overhead (~50MB RAM на sidecar, +5-10% CPU).
  • Сложность дебага (теперь и Envoy надо смотреть).
  • Latency +1-3ms per hop.

Новый подход без sidecars: per-node ztunnel (для L4: mTLS, ID) + per-namespace waypoint proxy (для L7: HTTP routing).

Pros: меньше overhead (один ztunnel на node вместо sidecar на pod). Cons: новее, меньше production deployments.

Нужен:

  • Десятки+ микросервисов.
  • mTLS обязателен (compliance).
  • Multi-team разработка с разными tech stacks.
  • Сложные traffic management требования (canary, mirroring).

Не нужен:

  • Маленький проект (<5 сервисов) — sidecar overhead не окупится.
  • Простой north-south case — API Gateway достаточно.
  • Высокие требования к latency (<1ms p99) — каждый hop добавляет.

Самый популярный API Gateway. Open source, на NGINX + Lua. Enterprise version от Kong Inc.

Архитектура:

  • DB-backed (PostgreSQL/Cassandra) или DB-less (declarative YAML).
  • Plugins: auth (JWT, OAuth2, key-auth), rate-limiting, transformations, logging, monitoring.

Конфиг:

services:
- name: payment-service
url: http://payment-svc:8080
routes:
- paths: ["/payments"]
plugins:
- name: rate-limiting
config:
minute: 100
- name: jwt

Kong поддерживает Go plugins через go-pdk. Можно писать custom logic на Go.

Go-native API Gateway. Stateless, конфиг через JSON, очень быстрый.

Конфиг (krakend.json):

{
"endpoints": [
{
"endpoint": "/api/order/{id}",
"method": "GET",
"backend": [
{
"url_pattern": "/orders/{id}",
"host": ["http://order-svc"]
},
{
"url_pattern": "/customers/{customer_id}",
"host": ["http://customer-svc"]
}
]
}
]
}

Aggregation из коробки. Конфигом задаются backends, KrakenD сам делает параллельные запросы и мерджит JSON.

Go-native, открытый код. Сильнее в API management (versioning, analytics, developer portal).

Envoy сам по себе — proxy, не API Gateway. Но с конфигом можно использовать как gateway.

listeners:
- address: { socket_address: { address: 0.0.0.0, port_value: 80 } }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
route_config:
virtual_hosts:
- name: payment
domains: ["*"]
routes:
- match: { prefix: "/payments" }
route: { cluster: payment-service }
http_filters:
- name: envoy.filters.http.jwt_authn
- name: envoy.filters.http.ratelimit
- name: envoy.filters.http.router

Envoy Gateway (CNCF проект 2023) — управление Envoy через Kubernetes Gateway API.

Для простых случаев — собственный gateway на chi/gin/echo.

Пример на chi:

package main
import (
"net/http"
"net/http/httputil"
"net/url"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
// Common middleware
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(authMiddleware)
r.Use(rateLimitMiddleware)
// Routing
r.Handle("/payments/*", proxyTo("http://payment-svc:8080"))
r.Handle("/orders/*", proxyTo("http://order-svc:8080"))
r.Handle("/users/*", proxyTo("http://user-svc:8080"))
http.ListenAndServe(":80", r)
}
func proxyTo(target string) http.Handler {
u, _ := url.Parse(target)
proxy := httputil.NewSingleHostReverseProxy(u)
proxy.ModifyResponse = func(r *http.Response) error {
r.Header.Set("X-Gateway", "go-gw")
return nil
}
return proxy
}
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
claims, err := validateJWT(token)
if err != nil {
http.Error(w, "unauthorized", 401)
return
}
r.Header.Set("X-User-ID", claims.Subject)
next.ServeHTTP(w, r)
})
}
func rateLimitMiddleware(next http.Handler) http.Handler {
limiter := rate.NewLimiter(1000, 100) // 1000 req/s, burst 100
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "rate limit", 429)
return
}
next.ServeHTTP(w, r)
})
}

Когда custom gateway оправдан:

  • Простые routes (<20).
  • Специфичные требования, не покрываемые Kong/KrakenD.
  • Команда сильна в Go.

Когда нет:

  • Сложные plugins (auth provider integration, observability).
  • Много routes — поддерживать дороже.
  • Не хватает экспертизы.

Самый feature-rich service mesh. Envoy data plane + Istiod control plane.

Установка:

Окно терминала
istioctl install --set profile=default
kubectl label namespace prod istio-injection=enabled

После label — Istio injects Envoy sidecar в каждый новый pod автоматически.

Traffic management через VirtualService:

apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: payment
spec:
hosts:
- payment
http:
- match:
- headers:
user-agent:
regex: ".*Mobile.*"
route:
- destination:
host: payment
subset: v2
- route:
- destination:
host: payment
subset: v1
weight: 90
- destination:
host: payment
subset: v2
weight: 10

10% трафика на v2 (canary), плюс mobile получает v2 целиком.

DestinationRule для CB:

apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: payment-cb
spec:
host: payment
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s

Lightweight service mesh. Rust data plane (linkerd2-proxy), Go control plane.

Преимущества:

  • Проще, меньше overhead (~10MB RAM per sidecar vs Istio’s 50MB).
  • Опеннисить и поддерживать.
  • Лучше latency.

Недостатки:

  • Меньше функций (например, ограниченный traffic shaping).
  • Меньше экосистема.

Установка:

Окно терминала
linkerd install | kubectl apply -f -
kubectl annotate ns prod linkerd.io/inject=enabled

Service mesh от HashiCorp. Intergates с Consul service registry.

Features: mTLS, intentions (firewall rules), observability. Слабее Istio в traffic management.

gqlgen — самая популярная Go библиотека. Schema-first, codegen.

Workflow:

  1. Описываешь schema в .graphql файле.
  2. Запускаешь go run github.com/99designs/gqlgen generate.
  3. Реализуешь resolvers.

Schema:

type Query {
order(id: ID!): Order
}
type Order {
id: ID!
total: Float!
customer: Customer!
items: [Item!]!
}
type Customer {
id: ID!
name: String!
email: String!
}
type Item {
id: ID!
title: String!
price: Float!
}

Resolver:

func (r *queryResolver) Order(ctx context.Context, id string) (*model.Order, error) {
return r.orderService.Get(ctx, id)
}
func (r *orderResolver) Customer(ctx context.Context, obj *model.Order) (*model.Customer, error) {
return r.customerService.Get(ctx, obj.CustomerID)
}
func (r *orderResolver) Items(ctx context.Context, obj *model.Order) ([]*model.Item, error) {
return r.itemService.ListByOrder(ctx, obj.ID)
}

Если у заказа 100 items и каждый item имеет customer (отдельный resolver), то 100 запросов в customer service — это N+1 проблема.

DataLoader pattern: батчинг + кэширование.

import "github.com/graph-gophers/dataloader/v7"
type CustomerLoader struct {
loader *dataloader.Loader[string, *Customer]
}
func NewCustomerLoader(svc *CustomerService) *CustomerLoader {
batch := func(ctx context.Context, ids []string) []*dataloader.Result[*Customer] {
customers, err := svc.BatchGet(ctx, ids)
results := make([]*dataloader.Result[*Customer], len(ids))
if err != nil {
for i := range ids {
results[i] = &dataloader.Result[*Customer]{Error: err}
}
return results
}
m := make(map[string]*Customer)
for _, c := range customers { m[c.ID] = c }
for i, id := range ids {
results[i] = &dataloader.Result[*Customer]{Data: m[id]}
}
return results
}
return &CustomerLoader{loader: dataloader.NewBatchedLoader(batch)}
}
// В resolver
func (r *orderResolver) Customer(ctx context.Context, obj *Order) (*Customer, error) {
return r.customerLoader.Load(ctx, obj.CustomerID)()
}

DataLoader собирает все Load() calls в течение тика, выполняет один Batch запрос.

В GraphQL клиент посылает query (текст), сервер парсит. Угрозы:

  • Огромные queries (DOS).
  • Малоизвестные queries (DOS).

Persisted queries: клиент посылает только hash, сервер ищет в whitelist.

// Client отправляет:
POST /graphql
{ "id": "5f3a4b2c", "variables": {"id": "123"} }
// Server resolves id → query → executes.

Используется Apollo Client, Relay. Защищает от arbitrary queries.

GraphQL subscriptions для real-time. WebSocket transport.

type Subscription {
orderUpdates(orderID: ID!): Order
}

gqlgen поддерживает через Server.AddTransport(transport.Websocket{}).

⚠️ WebSocket сложнее scale, чем HTTP. Sticky session, или Redis pub/sub broadcast между instances.


⚠️ Gateway — single point of failure. Деплой gateway в HA (>1 instance), TLS terminate behind LB.

⚠️ Долгие requests заполняют gateway. Если backend медленный, gateway connections заняты → новые клиенты не пройдут. Тaймауты + concurrency limits.

⚠️ JWT validation overhead. Каждый запрос — RSA verify (CPU-intensive). Cache verified tokens на TTL.

⚠️ CORS в gateway vs service. Стандартизуй: либо gateway добавляет, либо service. Иначе либо дубли, либо пропуски.

⚠️ Headers форвардинг. X-Forwarded-For, X-Real-IP, X-Request-ID должны прокидываться. Service видит реальный client IP, не gateway IP.

⚠️ X-Forwarded-Proto. Если gateway терминирует TLS, downstream видит HTTP. Если внутри генерируется ссылка — она будет http://, не https://. Используй X-Forwarded-Proto header.

⚠️ Sticky session vs scaling. Если sticky session в gateway (одну session на один backend pod), scaling и rolling deploy ломают. Хранить session в Redis.

⚠️ API versioning. /v1/orders vs /orders + X-API-Version header. Header version часто проще для gateway routing.

⚠️ Aggregation: failure handling. Если из 3 backends один упал, что вернуть? Partial response, 503, default values? Зависит от UX.

⚠️ Sidecar overhead в маленькой системе. 100MB RAM (Istio) на каждый pod × 50 pods = 5GB только на mesh. Бюджет!

⚠️ mTLS rotation. Sidecar обновляет cert автоматически (24h TTL обычно). Если падает control plane — certs истекают → outage.

⚠️ Envoy retry vs client retry. Двойной retry мультиплицирует нагрузку. Disable один из них.

⚠️ GraphQL N+1. Без DataLoader каждый поле — отдельный запрос. Профилируй! Используй tracing.

⚠️ GraphQL DOS. Глубокие nested queries: user { posts { comments { author { posts { ... } } } } }. Limit query depth и complexity.

⚠️ GraphQL authorization. Поля не имеют URL → авторизация на каждом поле. Используй middleware на resolver level.

⚠️ BFF дублирование. Без чёткого ownership одна логика реплицируется в нескольких BFF. Code review, shared libs.

⚠️ Gateway не replaces auth in services. Если злоумышленник попадёт мимо gateway (внутри сети), сервис не должен слепо доверять. Defense in depth: mTLS, JWT validation в сервисе тоже.


Netflix Zuul / Zuul 2. Zuul 1 — gateway на Java, синхронный (blocking). Zuul 2 — async, Netty-based. Netflix постепенно мигрировал на Envoy + custom control plane.

Kong на Cloudflare Workers. Cloudflare Workers — edge compute platform. Можно использовать как distributed API gateway, JS/Rust/Wasm.

Tinder API Gateway. Кастомный на Go. Routing, auth, rate limit, A/B test traffic splitting. Open sourced как tron (часть).

Spotify GraphQL BFF (Apollo Federation). Spotify использует federated GraphQL: gateway соединяет схемы от разных subgraphs (microservices). Apollo Federation.

GitHub GraphQL API. GitHub предоставляет GraphQL API параллельно с REST. Persisted queries для security и performance. https://docs.github.com/en/graphql

Shopify API Gateway. Кастомный gateway, оптимизированный для GraphQL. Shopify ranks one of largest GraphQL deployments. Federated.

Uber — Edge Gateway. Изначально custom, мигрировали на gRPC + Envoy. Service mesh внутри.

Lyft Envoy. Envoy создан в Lyft (2016), Open sourced, теперь CNCF. Используется как edge proxy и sidecar.

Yandex.Cloud API Gateway. Cloud-managed API Gateway. Поддержка OpenAPI specs, auth via Cloud Identity, integration с Functions.

Tinkoff API Gateway. Внутренний gateway на Go. Routing, JWT, rate limit, observability (OpenTelemetry).

Istio adoption. Используется eBay, Salesforce, IBM Cloud, Cisco Webex, Mux. Сложности — Lyft изначально создал Envoy специально, потому что других решений не было. Istio добавил complexity layer поверх.

Linkerd adoption. Microsoft, Walmart, Salesforce, HSBC. Многие выбирают Linkerd за простоту.

KrakenD у Saude (Brazil healthtech). KrakenD ~13K req/s на 1 pod 1 CPU. Aggregation 3-4 backends в один endpoint.

Cloudflare API Shield. Edge service: API discovery, schema validation, ML-based abuse detection. Managed API gateway.


Q1: Что такое API Gateway? A: Single entry point для backend services. Делает routing, auth, rate limiting, transformation, aggregation. Защищает от прямого доступа клиентов к internals.

Q2: Какие функции должен иметь API Gateway? A: Routing, authentication, rate limiting, request/response transformation, TLS termination, observability, optionally aggregation и caching.

Q3: Что не должно быть в gateway? A: Business logic, persistent state. Gateway — тонкий слой. Бизнес-правила — в сервисах.

Q4: North-south vs east-west traffic — в чём разница? A: North-south — между клиентами и системой (gateway). East-west — между микросервисами внутри (service mesh).

Q5: Какие популярные API Gateway существуют? A: Kong (NGINX-based), KrakenD (Go-native), Tyk (Go), Envoy (proxy), Cloud-managed (AWS API Gateway, Cloudflare).

Q6: Когда писать custom gateway на Go? A: Простые routes (<20), специфичные требования, команда сильна в Go. Не для сложных кейсов (auth providers, observability).

Q7: Что такое BFF (Backend for Frontend)? A: Отдельный backend для каждого frontend (mobile, web, partner). Каждый BFF оптимизирован под нужды клиента. Pattern Sam Newman 2015.

Q8: Зачем BFF, а не один универсальный API? A: Mobile хочет компактные данные (battery), web — богатые с relationships, partners — стабильный contract. BFF изолирует каждый клиент.

Q9: Что такое aggregator pattern? A: Gateway/BFF собирает данные из нескольких сервисов в один ответ. Снижает N+1 для клиентов (один запрос вместо нескольких).

Q10: Как сделать параллельные запросы в Go? A: errgroup.WithContext запускает goroutines, ждёт всех. При ошибке одного — отменяет остальные через context.

Q11: Что такое service mesh? A: Инфраструктурный слой для service-to-service. Sidecar proxy (Envoy) на каждом pod’е. Решает discovery, mTLS, retries, observability на инфра-уровне.

Q12: Когда service mesh не нужен? A: Маленькая система (<5 сервисов), простой north-south case, требования к ultra-low latency (<1ms p99). Overhead не окупается.

Q13: В чём разница Istio и Linkerd? A: Istio — feature-rich, Envoy proxy, ~50MB RAM/sidecar. Linkerd — lightweight, Rust proxy, ~10MB. Istio для enterprise, Linkerd для большинства.

Q14: Что такое Ambient Mesh? A: Istio 2024+ подход без sidecars. Per-node ztunnel + per-namespace waypoint proxy. Меньше overhead, новее.

Q15: Что такое GraphQL и зачем? A: Query language для API. Клиент выбирает поля и связи в одном запросе. Подходит для BFF: разные клиенты с разными нуждами.

Q16: Какая популярная Go библиотека для GraphQL? A: gqlgen (99designs) — schema-first, code generation. graphql-go — code-first.

Q17: Что такое N+1 проблема в GraphQL? A: Каждый nested field вызывает отдельный resolver. Список из N items с relations → N+1 запросов в downstream. Решение: DataLoader (батчинг + кэш).

Q18: Persisted queries — что это? A: Клиент посылает hash вместо текста query. Сервер ищет в whitelist. Защита от arbitrary queries, DOS. Apollo Client, Relay.

Q19: Как защитить GraphQL от DOS? A: Query depth limit, complexity scoring (cost per field), persisted queries, rate limit на queries (не на HTTP calls).

Q20: GraphQL vs REST для BFF — что выбрать? A: GraphQL — гибкость для разных клиентов, меньше эндпоинтов. REST — проще caching, простой routing. GraphQL для variety frontends, REST для simple/stable contracts.


  1. Реализуй простой API Gateway на chi с middleware: auth (JWT), rate limit (Redis), logging, proxy на 3 backend services.

  2. Aggregator endpoint. Endpoint /order/details делает параллельно 3 вызова к order/customer/items services через errgroup. Сравни latency vs sequential.

  3. JWT validation middleware с JWKS rotation. Кэшируй keys, refresh при unknown kid.

  4. Rate limiting с token bucket в Redis. Key = client IP. 100 req/min, burst 20.

  5. Установи Istio в minikube, задеплой 2 сервиса. Включи mTLS (PeerAuthentication STRICT). Покажи захват трафика на mTLS handshake.

  6. Canary deployment с Istio. VirtualService: 90% на v1, 10% на v2. Метрики через kiali.

  7. GraphQL сервер с gqlgen. Schema Order/Customer/Items. Resolvers с DataLoader для customer.

  8. Сравни overhead Linkerd vs Istio. Деплой 10 pods с/без mesh. Замерь RAM, CPU, latency.

  9. BFF для mobile и web. Mobile BFF возвращает compact JSON (только id, title), web — полный объект. Один backend на двух конце.

  10. Persisted queries. Whitelist queries по hash в server-side store. Client отправляет hash.


  1. Sam Newman. “Pattern: Backends For Frontends.” 2015. https://samnewman.io/patterns/architectural/bff/
  2. Chris Richardson. “Microservices Patterns.” Manning, 2018. — главы про API Gateway.
  3. Kong Documentation. https://docs.konghq.com
  4. KrakenD docs. https://www.krakend.io/docs/
  5. Istio Documentation. https://istio.io/latest/docs/
  6. Linkerd Documentation. https://linkerd.io/2/overview/
  7. Envoy Proxy Documentation. https://www.envoyproxy.io/docs/envoy/latest/
  8. gqlgen documentation. https://gqlgen.com/
  9. Apollo Federation. https://www.apollographql.com/docs/federation/
  10. Lin Sun, Daniel Berg. “Istio in Action.” Manning, 2022.
  11. William Morgan. “The Service Mesh: What every software engineer needs to know about the world’s most over-hyped technology.”
  12. CNCF Service Mesh landscape. https://landscape.cncf.io/