У тебя уже есть портфолио
Самая частая ошибка на этой стадии — думать, что портфолио надо строить с нуля. Открыть пустой репозиторий, придумать датасет, неделями ваять что-то новое. И вот тут будущий junior сгорает: новых проектов получается три недоделанных, на разных данных, без общей истории.
Стоп. Ты прошёл этот курс и (скорее всего) соседние. За спиной у тебя уже лежат готовые капстоны:
- Капстон DEF — NYC Taxi end-to-end ELT pipeline (raw -> DWH -> dbt -> dashboard, опц. Airflow).
- Капстон
python-fundamentals— ETL из GitHub API: API -> JSONL.gz -> Parquet -> Postgres, с тестами и CI. - Капстон
rest-api-fundamentals— multi-source ingestion: CoinGecko + GitHub, разные auth, retry, Parquet partition by date. - Капстон
dbt-i— Jaffle Shop: staging -> intermediate -> marts, тесты, snapshot, docs, lineage.
Это не черновики. Это и есть твоё портфолио. Задача урока — не построить новое, а консолидировать построенное в 2-3 закреплённых (pinned) проекта, которыми ты владеешь целиком и про которые можешь говорить 5 минут без запинки.
Антипаттерн, который убивает джунов: 6 разрозненных репозиториев на 6 разных датасетах, каждый “недо”. Работодатель сканирует 2-3 закреплённых end-to-end проекта, а не считает количество репо. Лучше 2 глубоких, чем 6 поверхностных. Меньше репо, больше глубины в каждом.
Зачем именно pinned-проекты
Junior DE — это переходный статус. Опыта в работе ещё нет, но компания должна понять, что ты умеешь руками. Если в вакансию приходит 200 откликов от джунов, и у 195 в резюме только курсы — резюме с end-to-end проектом сразу выделяется. Закреплённый проект — это твой главный артефакт на собеседовании.
Pinned-проект решает три задачи:
- Демонстрация навыков. Не “учил Airflow”, а “написал DAG, выкатил в Docker, есть git-репозиторий — посмотреть”.
- Тема разговора на интервью. Собеседующий просит рассказать про проект — у тебя есть готовая 5-минутная история, ты говоришь уверенно.
- Реальный опыт. В процессе делания капстонов ты сталкивался с настоящими граблями — broken CSV, API rate limits, MERGE-конфликты. Это и есть DE-experience.
Что не работает в портфолио:
- “Прошёл курсы Coursera / Udemy”. Это не проект, это потребление.
- “6 микро-репо по 50 строк кода”. Покажи 2-3 нормальных вместо 6 трешовых.
- “Без README, без описания, без коммитов”. Никто не будет копаться.
- “Параллельные рельсы, которые не встречаются” — каждый капстон сам по себе, без общей истории.
Стратегия консолидации
Идея простая: возьми готовые капстоны и сшей их в 2-3 проекта так, чтобы они рассказывали единую историю DE-инженера, а не выглядели набором учебных заданий.
Слева — что ты уже построил по курсам. Справа — как это группируется в 2-3 pinned-проекта
NYC Taxi -> BigQuery -> dbt -> dashboardПроект 1 (флагман): капстон DEF + выход BigQuery-лабы. raw -> облачный DWH -> dbt -> оркестрация -> дашборд. Полный end-to-end, которым владеешь целиком
multi-source ingestion в общий складПроект 2: капстоны Python + REST переосмыслены как один multi-source ingestion-сервис (API + файлы), грузящий в ОДИН общий датасет, а не в отдельные репо
dbt analytics engineeringПроект 3 (опц.): Jaffle Shop из dbt-i как самостоятельный analytics-engineering кусок — staging->marts, тесты, snapshots, docs, lineage
Три проекта — это не три копии одного. Они показывают разные грани: batch + cloud DWH (проект 1), ingestion из нескольких источников (проект 2), чистый analytics engineering на dbt (проект 3). Вместе — это breadth + depth.
Проект 1 (флагман): NYC Taxi -> облачный DWH -> dbt -> dashboard
Это твой главный pinned-проект. Берёшь капстон DEF и втягиваешь в него выход новой BigQuery-лабы, чтобы получить полный end-to-end с облачным DWH, а не только локальный DuckDB.
Капстон DEF: NYC Taxi end-to-end ELT — основа флагманского проектаКак сшить. Капстон DEF грузит NYC Taxi parquet в DuckDB/Postgres локально. Лаба BigQuery load показывает, как загрузить те же parquet-файлы в облачный DWH BigQuery через bq load. Соединяешь: ingester тот же, но теперь у тебя есть путь “грузим и в локальный DuckDB для dev, и в BigQuery для cloud-демо”. dbt-модели работают и там, и там (adapter меняется в profiles.yml).
Что показываешь. Полный цикл: raw parquet -> облачный DWH -> dbt (staging -> intermediate -> marts, тесты) -> оркестрация (Airflow DAG или cron) -> Streamlit-дашборд. На собеседовании это проект, про который ты говоришь: “я владею им целиком, от скачивания файла до графика на дашборде, включая cloud-загрузку”.
Стек. Python (ingester), BigQuery + DuckDB (DWH), dbt, Airflow (опц.), Streamlit, Docker Compose.
Главный технический challenge для рассказа. Партиционирование по дате, dimensional modeling (fact trips + dim date/zone), incremental dbt, загрузка в cloud DWH и контроль стоимости сканирования.
Проект 2: multi-source ingestion в общий датасет
Капстоны python-fundamentals и rest-api-fundamentals по отдельности выглядят как два учебных задания. Переосмысли их как один проект: ingestion-сервис, который тащит данные из нескольких источников — REST API и файлы — и грузит их в ОДИН общий склад/датасет, а не в два отдельных репозитория.
Как сшить. У обоих капстонов источник — внешний API, выход — Parquet или Postgres. Объедини: один Python-пакет с несколькими extract-модулями (GitHub Issues, CoinGecko prices, плюс источник-файл вроде CSV/parquet), общий слой нормализации (Pydantic-модели), общий load в одну Postgres-схему или один partitioned Parquet-датасет. Теперь это не “два проекта про API”, а “сервис, который собирает данные из разных источников в единое хранилище” — ровно то, чем DE занимается на работе.
Что показываешь. Multi-source extraction, разные схемы auth (API-key vs OAuth2), retry/backoff на 429/5xx, идемпотентность (upsert / partition-by-date), валидация Pydantic, тесты с моками (respx/VCR), CI на GitHub Actions, structured logging.
Стек. Python (httpx/requests, Pydantic, tenacity), Postgres или Parquet, pytest, GitHub Actions.
Главный технический challenge для рассказа. Как привести данные из разных источников к одной схеме, как сделать повторный запуск идемпотентным, как тестировать сетевой код без живых вызовов.
Проект 3 (опц.): analytics engineering на dbt
Если хочешь показать сильную analytics-engineering грань (особенно если целишь в роль AE) — закрепи капстон dbt-i Jaffle Shop как отдельный проект. Он уже git-версионируемый и подаётся как портфолио-кусок.
Что показываешь. Слои staging -> intermediate -> marts, dimensional modeling (dim/fact), 15-20 тестов (unique, not_null, relationships, accepted_values + singular), snapshot SCD2, exposures, сгенерированную документацию с lineage-графом.
Зачем отдельно от проекта 1. Проект 1 — про инфраструктуру и end-to-end. Проект 3 — про глубину моделирования и data quality. Это две разные компетенции, и держать их раздельно полезно: на AE-собеседовании ты пушишь проект 3, на DE-собеседовании — проект 1.
Когда пропустить. Если времени мало — оставь два проекта (1 и 2). Два сильных pinned-проекта лучше трёх средних.
GitHub-профиль: profile README и pinned repos
Рекрутер заходит на твой github.com/username и за 30 секунд решает, стоит ли копать. Два рычага: profile README и закреплённые репозитории.
Profile README
Это README.md в репозитории, имя которого совпадает с твоим username (username/username). GitHub показывает его на главной профиля. Шаблон для junior DE:
# Привет, я Имя — начинающий Data Engineer
Учусь строить data-pipelines: ingestion, DWH, dbt-моделирование,
оркестрация, дашборды. Ниже — мои закреплённые end-to-end проекты.
## Стек
SQL · Python · dbt · DuckDB / BigQuery / Postgres · Airflow · Docker
## Проекты (см. pinned ниже)
- NYC Taxi Analytics — end-to-end ELT в облачный DWH
- Multi-source Ingestion — сбор данных из нескольких API в один склад
- Jaffle Shop (dbt) — analytics engineering: staging -> marts, тесты, docs
Открыт к Junior DE / Analytics Engineer ролям.
Pinned repos
GitHub разрешает закрепить до 6 репозиториев — они показываются первыми. Закрепи именно 2-3 консолидированных проекта, не все подряд. Каждый закреплённый репо должен иметь говорящее имя (nyc-taxi-pipeline, не de-capstone-final-v2) и одну строку description, которую видно прямо в карточке.
Не закрепляй учебные форки, туториал-копии и пустышки. Пустой профиль с 3 сильными pinned-проектами выглядит лучше, чем профиль с 40 репо, где 37 — форки чужих туториалов.
Шаблон README на каждый проект
README — это лицо проекта. Собеседующий открывает GitHub за минуту, смотрит README и архитектуру. Если их нет — закрывает. Минимум, который должен быть в каждом pinned-проекте:
# NYC Taxi Data Pipeline
End-to-end ELT pipeline for NYC Taxi trip data:
ingestion -> cloud DWH (BigQuery) -> dbt -> dashboard.
## Architecture

Public parquet -> Python ingester -> BigQuery (+ local DuckDB for dev)
-> dbt (staging -> intermediate -> marts) -> Streamlit dashboard.
Orchestrated by Airflow (daily DAG).
## Stack
- Python 3.12 (ingestion)
- BigQuery (cloud DWH) / DuckDB (local dev)
- dbt 1.7 (transformations)
- Airflow 2.8 (orchestration)
- Streamlit (dashboard)
- Docker Compose
## Quick start
\`\`\`bash
docker compose up -d
# Airflow UI on localhost:8080, trigger DAG nyc_taxi_pipeline
\`\`\`
## Models
- stg_trips — raw trips, типизированные
- int_trips_clean — фильтр невалидных (negative fare, future date)
- mart_daily — aggregations by date / zone
## Design trade-offs
- DuckDB локально для быстрого dev-цикла; BigQuery для cloud-демо.
Один dbt-проект, adapter переключается в profiles.yml.
- Incremental dbt по дате вместо full-refresh: дешевле scan в BigQuery.
- Партиционирование по pickup_date — partition pruning на запросах дашборда.
## How it was tested
- dbt tests: unique trip_id, not_null pickup_time, accepted_values payment_type
- pytest на ingester (mock HTTP, проверка идемпотентности)
- CI на GitHub Actions: ruff + dbt build на каждый PR
Четыре блока, которые отличают сильный README от слабого:
- Диаграмма архитектуры — картинка (draw.io / Excalidraw), видно поток за 5 секунд.
- Design trade-offs — почему DuckDB локально, а BigQuery в облаке; почему incremental, а не full-refresh. Это показывает, что ты думал, а не копировал туториал.
- “How it was tested” — какие тесты, как проверял идемпотентность. Сигнал зрелости.
- Quick start —
docker compose upи всё работает. Если не запускается — проект не считается.
Самая частая ошибка — нет README или README в стиле “это мой проект, запускайте python main.py”. На собеседовании не успеют разобраться. README — это твоё резюме, а блок “Design trade-offs” — то, что отличает осознанного инженера от копипастера.
Как описать в резюме
Pet-project в резюме — это короткая секция. Каждый pinned-проект — название, стек в скобках, 2-3 буллета с конкретными числами, ссылка:
PROJECTS:
NYC Taxi Data Pipeline (Python, BigQuery, dbt, Airflow, Streamlit)
End-to-end ELT into a cloud DWH.
- Ingestion of monthly Parquet files into BigQuery + local DuckDB
- dbt: staging -> intermediate -> marts (15+ models, 30+ tests)
- Incremental processing with high-watermark by date
- Streamlit dashboard for daily/weekly metrics
github.com/username/nyc-taxi-pipeline
Multi-source Ingestion Service (Python, Postgres, Pydantic, pytest, CI)
Collects data from multiple APIs into a single warehouse.
- 3 sources (GitHub API, CoinGecko, CSV files) -> one Postgres schema
- Idempotent upsert, retry/backoff on 429/5xx, Pydantic validation
- pytest with HTTP mocks (respx/VCR), GitHub Actions CI
github.com/username/multi-source-ingestion
Принципы:
- Конкретные числа — 15 моделей, 30 тестов, 3 источника. Не “много данных”.
- Технологии в скобках — рекрутер сканирует за 5 секунд.
- Главный технический challenge — incremental, idempotency, multi-source.
- Ссылка на репо — обязательно.
Как рассказать историю “2-3 проекта” без опыта работы
У тебя нет строчки “работал в компании X”. Но у тебя есть история, и она логична: ты прошёл путь DE-инженера на учебных, но реальных задачах.
Скелет рассказа на собеседовании:
- “Я выстроил три проекта, покрывающих основные грани DE.”
- “Флагман — NYC Taxi pipeline: реальные данные, загрузка в облачный DWH, dbt-моделирование, оркестрация, дашборд. Я владею им целиком.” (Дальше — про конкретный challenge, например incremental + cost.)
- “Второй — ingestion-сервис из нескольких источников в один склад. Тут я разбирался с разными auth, идемпотентностью и тестированием сетевого кода без живых вызовов.”
- “Третий (если есть) — чистый dbt-проект: показывает, как я моделирую данные и слежу за качеством.”
Главное — не извиняться за отсутствие коммерческого опыта. Реальные грабли, на которые ты наступил (broken parquet, rate limit, MERGE-конфликт), — это и есть твой опыт. Говори о них как о работе.
Junior tip: один pinned-проект с чистым кодом, тестами, README и CI сильнее десяти со spaghetti-кодом. Делай меньше репозиториев, но доводи каждый до качественного состояния. Глубина важнее количества.
Где ещё показать проекты
- GitHub — основное (profile README + pinned).
- LinkedIn — в “Featured” секции с ссылкой и preview.
- Личный блог / dev.to — пост “что я построил и чему научился” — bonus для visibility.
- Видео-демо на YouTube — bonus, особенно для зарубежных компаний.
Про то, как этот же проект используется на самом собеседовании (как тема для system design и behavioral STAR-истории), — в следующем уроке.
Попробуй сам
- Открой все свои капстоны. Сгруппируй их в 2-3 pinned-проекта по схеме выше: флагман (DEF + BigQuery), multi-source ingestion (Python + REST), опц. dbt (Jaffle Shop).
- Для флагмана: соедини капстон DEF с выходом BigQuery-лабы так, чтобы dbt-модели запускались и на DuckDB, и на BigQuery. Допиши в README блоки “Design trade-offs” и “How it was tested”.
- Создай profile README (
username/username), закрепи 2-3 проекта, дай им говорящие имена и одну строку description каждому.