История перехода из позиции тестировщика в backend-разработчики: план, ресурсы, реальные сроки и результат — первый оффер через 8 месяцев подготовки.
Статья была полезной?
Я работал QA-инженером с 2019 года и в феврале 2025 года принял решение целенаправленно идти в backend. Прошло ровно восемь месяцев практики, кодинга и интервью — и в октябре 2025 я получил оффер на должность junior/mid backend-разработчика.
На момент старта у меня был опыт ручного и автоматизированного тестирования: Selenium, тест-планы, баг-репорты, базовые скрипты на Python для парсинга логов. Я не имел продвинутого опыта разработки серверной логики, но понимал жизненный цикл релиза, CI/CD и как устроены HTTP-запросы. Моя конкретная цель — через 8 месяцев получить первый оффер на backend-роль с реальными обязанностями над кодом (не только поддержка тестов), работать с Go и реляционными БД.
Я поставил чёткий план: учиться 20–25 часов в неделю, реализовать полноценный pet-проект с API, подготовиться к собеседованиям и подать 40–60 резюме. Начало: 1 февраля 2025, крайний срок — 1 октября 2025.
Когда я выбирал стек, учитывал рынковую востребованность и свой опыт: Go — популярный язык в backend, понятный синтаксис, статическая типизация. SQL — обязательный навык для большинства backend-вакансий. Первые два месяца (февраль — март 2025) были посвящены именно этим базам.
Минимальный пример HTTP-сервера на Go, который я писал первые недели:
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
_ "github.com/lib/pq"
)
func main() {
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "ok")
})
db, err := sql.Open("postgres", "host=localhost port=5432 user=dev dbname=test sslmode=disable")
if err != nil {
log.Fatal(err)
}
defer db.Close()
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
rows, err := db.Query("SELECT id, name FROM users LIMIT 10")
if err != nil {
http.Error(w, err.Error(), 500)
return
}
defer rows.Close()
for rows.Next() {
var id int
var name string
rows.Scan(&id, &name)
fmt.Fprintf(w, "%d: %s
", id, name)
}
})
log.Println("listening :8080")
http.ListenAndServe(":8080", nil)
}Простой SQL для создания таблицы и запроса, который я использовал при тестировании производительности:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT now()
);
-- запрос с индексом
CREATE INDEX idx_users_email ON users(email);
-- выборка с фильтрацией и сортировкой
SELECT id, name FROM users WHERE email LIKE '%@example.com' ORDER BY created_at DESC LIMIT 50;Через три месяца у меня уже был рабочий сервис на Go, подключённый к PostgreSQL. Я мог объяснить кандидатам по работе приложения жизненный цикл запроса, транзакции и отладку гонок (race conditions). Это дало мне уверенность для создания pet-проекта на следующем шаге.
Pet-проект стал ключевым доказательством моих навыков на собеседованиях. Я потратил апрель — июнь 2025 на реализацию полнофункционального сервиса: небольшой таск-трекер с REST API, авторизацией, миграциями и CI.
Пример handler'a для создания задачи:
func CreateTaskHandler(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct{ Title string `json:"title"` }
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
var id int
err := db.QueryRow("INSERT INTO tasks (title) VALUES ($1) RETURNING id", req.Title).Scan(&id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(map[string]int{"id": id})
}
}docker-compose.yml (фрагмент):
version: '3.8'
services:
db:
image: postgres:14
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: tasks
ports:
- "5432:5432"
app:
build: .
depends_on:
- db
ports:
- "8080:8080"Проект занял меня примерно 10 часов/неделю в течение трёх месяцев. К моменту активного поиска работы репозиторий имел README с инструкцией развертывания, описание API и ссылки на CI-пайплайн. Это значительно увеличило отклик от работодателей по сравнению с шаблонным резюме.
С мая 2025 я начал активно рассылать резюме и проходить собеседования. За период май — сентябрь 2025 я подал 58 резюме, прошёл 18 телефонных скринов и 9 технических интервью. Ключевое — регулярная подготовка и учёт типичных задач для backend.
Пример задания на собеседовании: «Напишите SQL-запрос, который для каждой задачи возвращает количество комментариев за последние 30 дней и сортирует по убыванию». Мой ответ:
SELECT t.id, t.title, COUNT(c.id) AS comments_count
FROM tasks t
LEFT JOIN comments c ON c.task_id = t.id AND c.created_at >= now() - interval '30 days'
GROUP BY t.id, t.title
ORDER BY comments_count DESC;Если спрашивали про гонки в Go — показывал пример использования mutex и channels, объяснял difference между buffered и unbuffered channels и как отлавливать race с помощью go test -race.
В октябре 2025 одну из компаний заинтересовал мой pet-проект и мой подход к решению задач: стартап в сфере B2B SaaS предложил позицию «Backend Engineer (Go)» с официальным оффером 180 000 ₽ в месяц на руки (gross 220 000 ₽) и опционами. Условия: гибридный режим, обучение внутри команды, участие в ревью кода. Оффер пришёл после финального интервью 28 сентября 2025; переговоры о зарплате завершились 3 октября 2025.
Переход из QA в backend не требует магии — нужна системность: фундаментальные знания, работающий проект и регулярная практика в интервью.
Оглядываясь назад, я вижу несколько конкретных вещей, которые можно было бы улучшить и ускорить переход.
Я недооценил важность понимания распределённых систем на более высоком уровне. Если бы я начал заниматься дизайн-уровнем в марте 2025 (а не в июле), то на собеседованиях я чувствовал бы себя увереннее при обсуждении очередей, k8s и схем репликации БД.
Если бы в апреле 2025 я начал вносить вклад в небольшие open-source проекты на Go, это бы добавило доверия к моему профилю. Даже 3–5 PR в популярных репозиториях демонстрируют умение работать с чужим кодом и проходить code review.
Я потратил много времени на unit-тесты, но интеграционные и нагрузочные тесты появились позже, когда уже были первые собеседования. Рекомендую писать их параллельно с функционалом, чтобы иметь готовые отчёты при показе проекта работодателю.
Я занимался подготовкой волнообразно: интенсивно перед собеседованием, затем спад. Лучше держать темп — 3–4 задачи по алгоритмам и 2 SQL задачи в неделю стабильно. Это помогает не терять скорость мышления при интервью.
Переход занял ровно восемь месяцев и потребовал дисциплины, но дал не только оффер: это новый набор навыков и понимание, как строятся серверные приложения. Если вы стремитесь к аналогичной цели, делайте ставку на реальный код, тесты и простую, но закончную архитектуру — это то, что работодатели видят в первую очередь.
Если хотите, могу выложить чек-лист из моих заметок по подготовке (шаблоны резюме, вопросы на интервью и список задач для pet-проекта) — напишите, какую часть хотите в первую очередь.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…