← все проекты
Dec 2022 — Now

Coperniq

Fullstack-разработчик / Team Lead

SaaS для управления проектами в solar-индустрии США. 200+ компаний-подрядчиков, 3000+ одновременных пользователей.

Метрики

−85%
Время ответа API (1.2с → 180мс)
−87%
Время деплоя (90 → 12 мин)
−60%
Production-инцидентов
12
Разработчиков в команде

Контекст

Coperniq — американский SaaS для управления проектами установки солнечных панелей: от продаж и пермитов до самого монтажа и пост-сервиса. Клиенты — 200+ компаний-подрядчиков среднего размера, у каждой по 5–50 активных проектов параллельно.

Когда я пришёл, платформа была одним Node.js-монолитом. Деплои по 90 минут, p50 MongoDB-запросов на критичных эндпоинтах — 1.2с, а ввод нового разработчика производил больше конфликтов, чем фич. Продукт работал, но каждый новый подрядчик делал следующий деплой ещё больнее.

Что я сделал

  • Спроектировал и провёл миграцию монолит → микросервисы. Выделил 5 сервисов: auth, projects, scheduling, billing, notifications. У каждого своя БД, схема, цикл деплоя.
  • Сделал real-time синхронизацию полевых работ на WebSocket. Бригады обновляют статус с мобильного, изменения долетают в офисные дашборды за <300мс. Тестировал на 3000 одновременных пользователей без бэклога в очереди.
  • Взял на себя всю работу с производительностью MongoDB: профилирование, составные индексы, переписывание pipeline-ов агрегации. p50 на критичных эндпоинтах упал с 1.2с до 180мс — на 85%.
  • Внедрил blue-green деплои в GitLab CI с health-чеками, автооткатом и canary-фазой: 5% трафика на новую версию 10 минут перед полной заменой.
  • Интегрировал с QuickBooks, Stripe, Google Maps и DocuSign — всё, чем подрядчики реально пользуются в работе.
  • Tech-лид команды из 4 fullstack-разработчиков: ревью, архитектура, 1:1, нанял 2 mid-уровня. Время до первого PR у новых сократилось с «3 недели» до «4 дня».

Технические решения

Границы сервисов выбирали по владению данными, не по «фичам» — billing владеет инвойсами и payment intents, scheduling владеет календарём бригад. Избежали антипаттерна «распределённый монолит», где сервисы шарят БД.

Межсервисное взаимодействие: синхронный REST для read-путей, где нужна консистентность; RabbitMQ-события для write-путей с eventual consistency. Saga для cross-service сценариев типа «проект завершён → инвойс → уведомление».

Frontend оставили монолитом на React + Redux Toolkit + React Query. RTK Query для серверного state, Redux — только для настоящего клиентского (модалки, драфты, optimistic UI). Убрали ~40% legacy Redux-boilerplate.

Observability: Prometheus + Grafana, структурированные JSON-логи в централизованный стек. У каждого микросервиса одинаковая тройка /metrics, /health, /ready — единообразие важнее, чем выбор идеального стека.

Из кода

javascript
Составной индекс, который починил медленный запрос
// Before: full collection scan on every dashboard load (~1.2s p50)
db.projects.find({
  organizationId: ObjectId("..."),
  status: { $in: ["in_progress", "permitting"] },
  scheduledStart: { $gte: ISODate("2026-01-01") },
}).sort({ scheduledStart: 1 }).limit(50);

// Compound index covering the filter + sort
db.projects.createIndex(
  { organizationId: 1, status: 1, scheduledStart: 1 },
  { name: "org_status_scheduled_v2", background: true }
);

// After: IXSCAN, ~180ms p50, no in-memory sort.
typescript
WebSocket fan-out с org-scoped комнатами
io.on("connection", (socket) => {
  const { orgId, userId } = socket.data.session;
  socket.join(`org:${orgId}`);
  socket.join(`user:${userId}`);
});

projectsEvents.on("status_changed", async (evt) => {
  // Push only to clients in the affected org, not all 3000.
  io.to(`org:${evt.orgId}`).emit("project.updated", {
    projectId: evt.projectId,
    status: evt.status,
    updatedBy: evt.actorId,
    ts: evt.timestamp,
  });
});

Результат

Команда выросла с 5 до 12 разработчиков без пропорционального падения velocity. Деплой: 90 → 12 мин. Production-инцидентов: −60%. API latency: 1.2с → 180мс.

До сих пор веду архитектурное ревью cross-service задач и провожу технические собесы fullstack-кандидатов.

Стек

TypeScriptNode.jsNest.jsExpressReactRedux ToolkitReact QueryMongoDBPostgreSQLRedisKubernetesAWSGitLab CIPrometheusGrafana