lenec ru

← все посты

Собеседование на мидла Backend: что реально спрашивают в 2026

16K

В 2026-м мидл-бэкенд — это уже не «знаю синтаксис языка и SQL». Чтобы пройти на сильную позицию, нужно держать в голове сетевые штуки, базы и параллельность. Я работаю как HR-консультант с разработчиками, и в этой статье собрала, что реально звучит на собесах в среднем по рынку — Авито, Озон, Сбер, Х5, Тинькофф (ныне Т-Банк), плюс продуктовые middle-size.

Темы общие, не привязаны к Java/Go/Python — но я отмечу, где есть язык-специфичные нюансы.

Раунд 1: разговор по резюме

Длится 30–45 минут. Задача — понять, как ты думаешь, что делал по делу. Типовые вопросы:

  • Расскажи, как устроена система, в которой ты сейчас работаешь.
  • Какой у вас стек, как принимались решения по ключевым технологиям, ты участвовал?
  • Какая самая сложная задача за последний год — что было сложного.
  • Как организован процесс выкатки, как тестируется, что в CI/CD.
  • Расскажи про инцидент в проде, в котором ты участвовал. Что произошло, как починили, что изменили после.

Главная ошибка — рассказывать в стиле «занимался разработкой и поддержкой». Дай конкретику. Если над фичей работали трое и ты делал треть — так и скажи. Если систему дизайнил тимлид, а ты её реализовывал — тоже честно. Интервьюер чувствует, когда чужие достижения присвоены.

Раунд 2: язык и платформа

Здесь тебя проверят на язык. Несколько примеров под мейнстримные стеки.

Java/Kotlin

  • JMM: что такое happens-before, volatile, synchronized.
  • GC: G1 vs ZGC, когда выбрать что.
  • Потоки и виртуальные потоки (Loom). Когда использовать виртуальные.
  • Spring: чем отличаются @Component, @Service, @Repository, что делает @Transactional «под капотом».
  • JPA: N+1 problem, как ловится и чинится.

Go

  • Goroutines, каналы, select. Зачем нужен runtime scheduler.
  • Контексты: как пробрасываются, что происходит при отмене.
  • Мютексы, sync.Once, sync.Pool — когда что.
  • Интерфейсы: dispatch, итераторы (после 1.23), generics.
  • Эскейп-анализ: что переезжает в кучу, как смотрит компилятор.

Python

  • GIL: что блокирует, что не блокирует. Почему многопоточность не ускоряет CPU-bound задачи.
  • asyncio: что внутри. Когда выбрать threading, multiprocessing.
  • uv/poetry/pip: чем отличаются и почему uv в 2026 фактически стандарт.
  • Pydantic v2 vs v1: производительность, миграции.
  • FastAPI: жизненный цикл запроса, dependency injection, BackgroundTasks.

Раунд 3: базы данных

Без этого мидла не пройти. Минимальный список:

  • Уровни изоляции: read uncommitted, read committed, repeatable read, serializable. Какие проблемы решает каждый.
  • Индексы: B-tree vs hash vs GIN/GIST. Когда какой нужен.
  • EXPLAIN ANALYZE — уметь читать план: seq scan vs index scan vs index only scan.
  • Транзакции в распределённых системах. Что такое two-phase commit и почему его обычно не используют.
  • Блокировки: row-level, table-level. SELECT ... FOR UPDATE, SKIP LOCKED.
  • Шардирование, репликация. Streaming replication в Postgres, чем отличаются sync и async.
  • Логические vs физические бэкапы. PITR.

Типовая задача: дам тебе схему таблицы и медленный запрос, попрошу ускорить. Решение — через прогон EXPLAIN, добавление индекса, иногда денормализация.

-- было: 1.4 секунды на 50 миллионах строк
SELECT * FROM orders
WHERE user_id = $1 AND status = 'paid'
ORDER BY created_at DESC LIMIT 20;

-- индекс на (user_id, status, created_at DESC)
CREATE INDEX idx_orders_user_status_created
  ON orders (user_id, status, created_at DESC);
-- стало: 2 миллисекунды

Раунд 4: API и инфраструктура

  • REST: идемпотентность, методы, коды ошибок. Чем PUT отличается от PATCH.
  • gRPC: когда использовать, формат сообщений, стриминг.
  • GraphQL: N+1, dataloader, cost analysis.
  • Очереди: Kafka vs RabbitMQ vs Redis Streams. Какие гарантии доставки даёт каждая.
  • Кэши: in-memory, Redis, CDN. Стратегии инвалидации.
  • Docker: multi-stage build, размер образа, security.
  • Kubernetes на уровне понимания: pod, service, ingress, что значит OOMKilled, liveness/readiness probes.
  • Мониторинг: метрики, логи, трейсы. Что в Prometheus, что в OpenTelemetry.

Один любимый вопрос интервьюеров: «как сделать ретраи правильно». Ответ — не «крутить в цикле try». Экспоненциальный бэкофф с jitter, лимит попыток, идемпотентность операции, dead letter queue для неудачных.

Раунд 5: system design

Это раунд, на котором сваливается большинство мидлов, считающих, что system design — для сеньоров. На уровне мидла никто не ждёт сверхдетального дизайна Netflix. Ждут структурного мышления.

Типовая задача: «Спроектируй сервис укорачивателей ссылок». Или «Спроектируй чат на миллион пользователей». Или «Сделай API для онлайн-аукциона».

План решения такой:

  1. Уточнить требования. Сколько RPS, какой размер записи, какие SLA.
  2. Накидать базовую схему: клиент → API → БД.
  3. Расширять: кэш, очередь, шардинг, репликация.
  4. Обсудить узкие места: где упрётся первым.
  5. Поговорить про мониторинг, аларминг, инциденты.

Не пытайся сразу впихнуть все технологии, которые знаешь. Это сразу читается. Веди диалог: «у нас уже база справится при 1000 RPS, кэш не нужен» — отличный ответ.

Раунд 6: задача на код

Не leetcode-mediumн hard. Чаще практичная задача:

  • Реализуй rate limiter (token bucket).
  • Сделай thread-safe LRU-кэш.
  • Распарси большой JSON стриминговым парсером.
  • Возьми текст, посчитай top-K слов.

Решай вслух. Сначала наивно, потом оптимизируй. Если упёрся — попроси подсказку, это нормально.

// Простой rate limiter на канале
type Limiter struct {
    tokens chan struct{}
}

func New(rate int, per time.Duration) *Limiter {
    l := &Limiter{tokens: make(chan struct{}, rate)}
    for i := 0; i < rate; i++ {
        l.tokens <- struct{}{}
    }
    go func() {
        ticker := time.NewTicker(per / time.Duration(rate))
        for range ticker.C {
            select {
            case l.tokens <- struct{}{}:
            default:
            }
        }
    }()
    return l
}

func (l *Limiter) Allow() bool {
    select {
    case <-l.tokens:
        return true
    default:
        return false
    }
}

Behavioral раунд

Метод STAR: situation, task, action, result. Подготовь 4–5 истории заранее.

  • Расскажи про конфликт в команде.
  • Когда ты ошибся — что было, как разрулил.
  • Расскажи про техническое решение, которое потом пришлось пересмотреть.
  • Расскажи про ситуацию, когда ты был не согласен с тимлидом.

Не пиши себя только героем. Хорошие истории — те, где ты ошибался, увидел, что не так, и поправился. Это сильно. Истории, в которых ты всегда прав, выглядят неискренне.

Что отличает мидла от джуна на собесе

  1. Мидл может объяснить почему техническое решение, не только что было сделано.
  2. Мидл говорит про trade-offs. Не «выбрали Postgres, потому что он лучший», а «Postgres, потому что нам нужны транзакции и сложные запросы, согласились на меньший throughput на запись».
  3. Мидл понимает свой блокирующий контур. Что в его коде узкое место, как мониторится, что произойдёт при пиковой нагрузке.
  4. Мидл умеет признавать «не знаю». И знает, где будет искать.

Что запомнить

Готовиться к мидл-собесу — это не «прочитал 500 вопросов на хабре». Это закрыть пробелы по своему стеку, прокачать system design (3–4 разобранных задачи закроют 80% сценариев), и научиться рассказывать про свой опыт через цифры и решения.

За четыре недели плотной подготовки большинство мидлов проходят отбор в желаемую компанию или получают понимание, что им не хватает, и закрывают это конкретной работой. Главное — ходить на собесы, даже если не собираешься менять работу. Это лучшая обратная связь по себе как инженеру, бесплатная.

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.