После многих лет работы с Java и Spring Boot я решил освоить Golang, думая, что это будет просто еще один язык для бэкенда в моем арсенале.

Я ошибался. Спустя шесть месяцев разработки SaaS-приложений продакшен-уровня я понял кое-что: Go не пытается быть лучшей версией Java или более простым Node.js.

Он создан для конкретной задачи — и эта задача заключается в работе SaaS-продуктов. Объясню, что я имею в виду.

Реальность счетов за использование облака

Вот с какой проблемой я столкнулся в прошлом году. Наше Spring Boot-приложение работало на AWS, и ежемесячные счета начинали нас неприятно удивлять.

У нас было 8 инстансов EC2 только для обработки среднего трафика, каждый потреблял минимум 4 ГБ оперативной памяти (потому что такова JVM).

В качестве эксперимента я переписал один из наших микросервисов на Go. Та же функциональность, те же конечные точки, та же бизнес-логика.

Результат? Один бинарник на Go справлялся с той же нагрузкой на инстансе t3.small (2 ГБ RAM), для которой раньше требовался t3.large (8 ГБ RAM). Наш счет AWS за этот сервис уменьшился на 60%.

Это не магия. Go компилируется в один бинарный файл, который содержит все необходимое. Никаких накладных расходов на JVM, никакого ада с зависимостями — просто код, работающий напрямую с «железом».

Когда вы платите за каждый гигабайт RAM и каждое ядро CPU в час, это имеет огромное значение.

Развертывание сделало меня ленивым (в хорошем смысле)

Со Spring Boot мой процесс развертывания выглядел так:

  • собрать JAR-файл;
  • убедиться, что на целевом сервере установлена нужная версия Java;
  • настроить параметры памяти;
  • установить переменные среды;
  • надеяться, что ничего не сломается.

С Go:

  • собрать бинарник под Linux;
  • скопировать его на сервер;
  • запустить.

И все. Один файл. Никаких зависимостей времени выполнения. Я могу собрать его на своем Mac и развернуть на Linux-сервере, даже не задумываясь.

Для SaaS-продуктов, которые нужно развертывать часто и надежно, такая простота бесценна.

Та самая история с конкурентностью (и почему это действительно важно)

Вы наверняка слышали про горутины. Все любят о них говорить. Но вот вам реальная история из моего опыта.

У нас была функция, где пользователи загружали CSV-файлы, а мы обрабатывали их в фоновом режиме. С Java я использовал пулы потоков и ExecutorService.

Это работало, но управление пулами потоков напоминало поддержку второго приложения. Сколько потоков? Какого размера очередь? Что произойдет под нагрузкой?

В Go я написал вот это:

for _, row := range csvRows {
    go processRow(row) // И все
}

Я не говорю, что стоит запускать горутины вот так, без всякого контроля (позже мы добавили нормальные пулы воркеров и ограничение частоты запросов).

Но суть в том, что Go делает конкурентное программирование настолько простым, что вы можете начать с простого решения и оптимизировать его позже. С потоками в Java нужно с самого начала делать все правильно, иначе придется расплачиваться в продакшене.

Для SaaS-приложений, работающих одновременно со множеством клиентов, эта способность к конкурентной обработке становится вашей отправной точкой, а не предметом оптимизации.

Проблема, которую Go не решает

Позвольте мне быть честным. Go не является идеальным решением для всего.

Создаете сложную административную панель с кучей бизнес-логики и проверок? Здесь я бы все еще выбрал Spring Boot.

Внедрение зависимостей, зрелая экосистема, поддержка ORM — Spring Boot делает сложные CRUD-приложения проще.

Простота Go становится ограничением, когда вам нужно что-то вроде следующего:

  • широкие возможности ORM (есть GORM, но это не Hibernate);
  • сложные паттерны внедрения зависимостей;
  • глубокие фреймворки, основанные на рефлексии;
  • «тяжелая» логика преобразования данных.

Я познал это на собственном горьком опыте, когда попытался создать внутренний инструмент администрирования на Go. Я потратил больше времени на ручную связку компонентов, чем потратил бы в Spring Boot. В таких сценариях Go заставляет вас писать больше шаблонного кода.

Где Go имеет преимущество: золотая середина для SaaS

По опыту создания трех продакшен-сервисов на Go могу сказать, где он неизменно выигрывает:

  • API-сервисы, которые должны быть быстрыми и экономичными. Пользовательский API, который обрабатывает аутентификацию, обслуживает данные, управляет запросами — это территория Go. Низкая задержка, низкое потребление ресурсов, легкость горизонтального масштабирования.
  • Фоновые обработчики и очереди задач. Обработка веб-хуков, отправка электронных писем, обработка загруженных файлов, выполнение запланированных задач. Модель конкурентности Go делает их эффективную реализацию почти тривиальной задачей.
  • Инструменты командной строки и утилиты. Если вашему SaaS нужны внутренние инструменты или клиентские CLI-приложения, компиляция Go в один бинарный файл — это то, что нужно. Мы поставляем инструмент для миграции базы данных как один исполняемый файл, и клиенты в восторге.
  • Сервисы, которым нужно быстро масштабироваться. Когда вы переходите от 100 пользователей к 10000 за одну ночь, вам нужно, чтобы затраты на инфраструктуру росли линейно, а не экспоненциально. Go в этом помогает.

В чем реальная разница

Мне хотелось бы, чтобы кто-то сказал мне раньше вот что: Go не конкурирует со Spring Boot или Express.js по функциональности. Он конкурирует в простоте эксплуатации и эффективности использования ресурсов.

Когда вы создаете SaaS-продукт, вы не просто пишете код — вы управляете затратами на инфраструктуру, конвейерами развертывания, мониторингом, масштабированием и временем безотказной работы. Go оптимизирован для всего этого жизненного цикла, а не только для этапа разработки.

Помните тот сервис на Spring Boot, о котором я упоминал ранее? Он все еще работает. Мы не заменили все на Go.

Мы используем оба инструмента. Spring Boot — для сложного уровня бизнес-логики, где важнее всего продуктивность разработчиков. Go — для API-шлюза, фоновых обработчиков и ресурсоемких сервисов, где важнее всего эффективность эксплуатации.

Мое мнение спустя 4 года

Если вы создаете SaaS-продукт с нуля сегодня, вот моя рекомендация: начните с того, что вы знаете. Если вам комфортно с Java и Spring Boot, используйте их. Не переписывайте все на Go только потому, что это модно.

Но вы можете столкнуться с конкретными проблемами:

  • высокими затратами на инфраструктуру для простых сервисов;
  • необходимостью в лучшей конкурентной обработке;
  • сложностью развертывания;
  • узкими местами масштабирования.

Вот тогда Go должен быть в вашем арсенале. Это не замена всему стеку. Это специализированный инструмент для тех частей SaaS-архитектуры, где эффективность эксплуатации напрямую влияет на прибыль.

Ведь в конечном итоге SaaS-бизнес измеряется уровнем маржинальности. А Go помогает сохранить больше заработанного, сокращая расходы на поддержание работы сервисов.


Читайте также:

Читайте нас в Telegram, VK и Дзен


Перевод статьи Abhinav: Golang Is Not a Backend Language — It’s a SaaS Language

Предыдущая статьяКак старшие фронтенд-инженеры используют ИИ в своей работе