Материал Эйч · Опубликовано 27 октября 2026
Техлид в домене «Управление контрагентами»: микросервисы, highload, команда и архитектура договорной автоматизации
Фишка: Акцент на собственные highload-решения, Everything as Code, стек с Kafka, ClickHouse, Event Sourcing и CQRS — часто спрашивают про консистентность и деградацию инфраструктуры, а не только про синтаксис C#.
| Этап | Длительность | Что проверяют |
|---|---|---|
| Скрининг / HR | 30–45 мин | Мотивация, опыт лидерства, формат работы, ожидания по роли и домену |
| Техническое интервью | 60–90 мин | C#, async/await, коллекции, ООП; PostgreSQL; разбор кода и SQL-задачи |
| Системное / архитектурное | 60–90 мин | Highload, брокеры, кэш, идемпотентность, outbox, инциденты в K8s |
| Лидерство / финал | 45–60 мин | Управление командой, декомпозиция, code review, коммуникация с бизнесом, культура Ozon Tech |
Обязательный минимум
Плюсом будет
Зачем нужны перегрузка, переопределение и перекрытие методов; в чём различие механизмов вызова?
Overload — compile-time по сигнатуре; override — virtual/override, runtime по типу объекта; new — скрытие, вызов по типу ссылки.
Что делают операторы is и as, чем они отличаются и где применяются?
is — проверка типа/pattern matching; as — безопасное приведение с null при неудаче; is не бросает исключение.
Опиши коллекции: array, list, hashset, dictionary — целевое назначение и отличия.
Array/List — индексный доступ; HashSet — уникальность O(1) contains; Dictionary — пары ключ-значение, порядок не гарантирован у HashSet/Dictionary.
Ловушка: Путать перекрытие (new) с переопределением (override) — на собесе часто просят нарисовать, какой метод вызовется.
Как работать с массивом из 100 000 элементов с точки зрения управления памятью?
Избегать лишних копий; Span/Memory; пулы массивов; struct vs class; LOH для больших объектов; рассмотреть ArrayPool<T>.
Совет: Для лида важно связать ответ с профилированием (dotMemory, PerfView) и реальными узкими местами в сервисах.
Что такое lock, как сделать инкремент атомарным, почему lock нельзя сочетать с await, чем SemaphoreSlim отличается от Semaphore и что будет при использовании value type как объекта синхронизации?
Interlocked для счётчика; lock + await — риск deadlock; SemaphoreSlim легче и для async; struct как lock — boxing/отдельные объекты, синхронизация не работает.
Приведите практический кейс использования SemaphoreSlim.
Ограничение параллелизма к внешнему API/БД; throttling; async-friendly wait/release.
Ловушка: Task.Result и .Wait() в async-коде — классическая тема на разборе BookTour.
Какие времена жизни сервисов существуют в стандартном DI-контейнере .NET и в чём их различие?
Singleton — один на приложение; Scoped — на scope (запрос); Transient — новый при каждом resolve. Опасность captive dependency.
Фишка: В микросервисах scoped обычно совпадает с HTTP-request; в фоновых воркерах scope создают вручную.
Какие индексы PostgreSQL вы знаете; чем B-tree отличается от hash, что такое кластерный и некластерный индекс и есть ли кластерный индекс в PostgreSQL?
B-tree — универсальный; hash — только =; в PG нет классического clustered как в SQL Server; CLUSTER перестраивает физический порядок таблицы.
Что такое VACUUM в PostgreSQL и какую проблему решает MVCC?
MVCC оставляет dead tuples; VACUUM очищает; autovacuum; bloat; visibility map.
Расскажи про опыт оптимизации сложных SQL-запросов и работы с планом выполнения. Был ли кейс ускорения в 2–3 раза?
EXPLAIN (ANALYZE, BUFFERS); индексы под WHERE/JOIN; переписывание подзапросов; статистика; избегать select *.
Совет: Готовь один конкретный кейс с цифрами до/после и какие индексы добавили.
Есть задача: атомарно записать событие в брокер (Kafka/RabbitMQ) и в базу данных. Как обеспечить транзакционность?
Transactional Outbox + relay; inbox; saga; 2PC обычно не вариант; идемпотентные consumers.
Как решить проблему деградации кэша (Redis отвечает за 1 секунду, БД за 10 мс)?
Метрики latency; circuit breaker; fallback на БД с лимитом; шардирование Redis; hot keys; сеть и persistence.
Если под в Kubernetes упал после успешного бронирования отеля, но до сохранения ID брони — как восстановить консистентность?
Идемпотентные ключи; saga/compensation; outbox; reconciliation job; не полагаться только на in-memory state.
Фишка: Домен контрагентов — длинные бизнес-процессы и согласования; консистентность и компенсации близки к реальным инцидентам.
Code review: BookTour
Дан метод бронирования тура с параллельным вызовом авиа и отеля через Task.WhenAll, catch с отменой, finally с RunSynchronously и инкрементом счётчика. Найди проблемы: enum из строк, .Result, компенсации при ошибках, инициализация полей в finally, потокобезопасность счётчика.
TryParse для enum; await вместо Result; AggregateException в WhenAll; корректные ID для cancel; не сохранять в finally после ошибки; Interlocked.Increment; вынести GetUser; рассмотреть TransactionScope/outbox для согласованности.
Сложность: O(1) на вызов; риск в блокировках и гонках
SQL: первый альбом артиста
Таблицы Artists и Albums. Вернуть имя артиста, название и дату самого раннего альбома для каждого артиста.
Вариант с подзапросом MIN(release_date) по artist_id или CTE: group by artist_id, min(release_date), join обратно к Albums по дате и id. Внимание к именам колонок artistId vs artist_id в схеме.
Сложность: O(n log n) при сортировке; с индексом (artist_id, release_date) — эффективный lookup
Каркас ответа
3 дня
7 дней
14 дней
| Блок | Готов, если... |
|---|---|
| C# concurrency | можешь объяснить, почему lock+await опасен, и предложить SemaphoreSlim для throttling |
| PostgreSQL | можешь объяснить VACUUM и выбрать индекс под запрос с JOIN |
| Распределённость | можешь нарисовать Outbox Pattern от HTTP до Kafka |
| Лидерство | есть два STAR-кейса: команда + инцидент/бизнес |
В день собеседования