PHP, Node.js или Go: какой бэкенд выбрать
Чем PHP, Node.js и Go отличаются для серверной части: тринадцать критериев, какой язык под какой проект, как разница проявляется на практике, один API на всех трёх и частые ошибки.
Коротко
PHP, Node.js и Go — три самых частых выбора для серверной части веб-проекта, и каждый выигрывает на своём месте. PHP — самый быстрый путь к сайту, магазину или админке: хостинг везде, каждый запрос с чистого листа, огромная экосистема. Node.js — выбор, когда фронтенд на JavaScript или TypeScript и сервер должен делить с ним код и типы или когда много реального времени — чаты, уведомления, живые данные. Go — для сервисов, которые должны держать высокую нагрузку на скромном железе со стабильным временем ответа: API, очереди, шлюзы. Многие проекты используют два из них рядом.
Коротко: что выбрать
Начните с того, чем сервер в основном занят. Если он собирает страницы, обрабатывает формы и обслуживает админку — это родная стихия PHP: дёшево в хостинге, быстро в разработке, легко найти разработчиков. Если он держит тысячи открытых соединений или делит логику с интерфейсом на React — Node.js. Если это API под настоящей нагрузкой, обработчик очередей или шлюз, который должен отвечать за миллисекунды при любом трафике, — Go.
Выбор не исключающий. Типичная здоровая схема: сайт и админка на PHP, нагруженная часть на Go, а сборка интерфейса — на Node.js и Vite. Каждый язык делает то, что у него лучше всего получается.
- Сайты и админки — PHP
- Реальное время и общий код — Node.js
- Нагрузка и стабильные задержки — Go
PHP, Node.js и Go: подробное сравнение
Тринадцать критериев рядом. Скорость зависит от кода и базы, поэтому в таблице — взаимное положение, а не бенчмарки.
| Критерий | PHP | Node.js | Go |
|---|---|---|---|
| Модель запроса | каждый запрос с чистого листа | один процесс, цикл событий | горутина на запрос |
| Типизация | динамическая + строгие типы по желанию | с TypeScript — статическая при сборке | статическая, проверяет компилятор |
| Скорость под нагрузкой | хорошая с OPcache | высокая на вводе-выводе | самая высокая из трёх |
| Память | на воркер; много воркеров складываются | один процесс, умеренно | экономнее всех |
| Долгие соединения | с доп. инструментами | из коробки | из коробки |
| Тяжёлые вычисления | слабо | блокирует цикл, нужны потоки | сильно, использует все ядра |
| Хостинг | любой, включая виртуальный | VPS или платформа | VPS, один файл |
| Выкладка | скопировать файлы | код плюс node_modules, менеджер процессов | один бинарник, менеджер процессов |
| Готовые CMS и магазины | больше всего | немного | почти нет |
| Общий код с фронтендом | нет | да, один язык | нет |
| Скорость разработки | очень высокая для сайтов | высокая | высокая, когда основа написана |
| Разработчиков на рынке | очень много | очень много | меньше, но растёт |
| Лучше всего для | сайтов, магазинов, админок | реального времени, API для React, ботов | нагруженных API, очередей, шлюзов |
Какой язык под какой проект
Двенадцать типичных проектов с рекомендацией и причиной.
| Проект | Брать | Почему |
|---|---|---|
| Корпоративный сайт или лендинг | PHP | недорогой хостинг, быстрая разработка |
| Интернет-магазин или каталог | PHP | классическая задача с самой богатой экосистемой |
| Админка или CRM | PHP | формы, таблицы и роли — его повседневная работа |
| API для интерфейса на React | Node.js | общие типы и один язык |
| Чат, уведомления, живые данные | Node.js или Go | открытые соединения — родная стихия обоих |
| Telegram-бот и Mini App | Node.js или Go | долгоживущие процессы и хорошие библиотеки |
| Сайт на Next.js | Node.js | серверной отрисовке React он нужен |
| Нагруженный API | Go | стабильные задержки и мало памяти |
| Обработчик очередей и интеграций | Go | горутины обрабатывают тысячи задач параллельно |
| Шлюз или прокси | Go | стандартная библиотека создана для сети |
| Импорт и скрипты по расписанию | любой | тот, что уже есть в проекте |
| Только виртуальный хостинг | PHP | остальным нужен VPS |
Как разница проявляется в настоящем проекте
-
Утечка памяти
В PHP она умирает вместе с запросом; в Node.js и Go растёт, пока процесс не перезапустят, — нужен мониторинг.
-
Необработанная ошибка
В PHP она ломает один запрос; в Node.js может уронить весь процесс; в Go паника в обработчике перехватывается сервером.
-
Десять запросов к чужим API
PHP делает их по очереди, если не взять curl_multi; Node.js и Go — параллельно, естественным образом.
-
Пик трафика
PHP нужны достаточное число воркеров и память под них; Go поглощает пик горутинами; Node.js — пока ничто не блокирует цикл.
-
Обновление на сервере
PHP — скопировать файлы; Go — заменить один бинарник и перезапустить; Node.js — поставить зависимости и перезапустить.
-
Через пять лет
Код на Go и чистом PHP стареет медленно; проект на Node.js с множеством зависимостей требует регулярных обновлений.
Один API на трёх языках
Один и тот же адрес — список товаров с фильтром по цене — на PHP, Node.js и Go. Каждый запущен настоящим сервером и дал одинаковый ответ.
PHP
Файл, который выполняется с нуля на каждый запрос, — никакого серверного кода, который нужно держать живым.
<?php
declare(strict_types=1);
// PHP: каждый запрос выполняет файл с чистого листа — состоянию нечему утечь между запросами
$products = [
['sku' => 'A-100', 'title' => 'Дубовый стол', 'price' => 24000],
['sku' => 'B-200', 'title' => 'Сосновая полка', 'price' => 5000],
];
if (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) !== '/api/products') {
http_response_code(404);
exit;
}
$max = (int) ($_GET['max'] ?? PHP_INT_MAX);
header('Content-Type: application/json');
echo json_encode(
array_values(array_filter($products, fn(array $p): bool => $p['price'] <= $max)),
JSON_UNESCAPED_UNICODE,
);
Node.js
Один долгоживущий процесс на встроенных модулях; тот же язык, что у интерфейса.
import { createServer } from 'node:http';
// Node.js: один долгоживущий процесс, цикл событий обслуживает каждый запрос
const products = [
{ sku: 'A-100', title: 'Дубовый стол', price: 24000 },
{ sku: 'B-200', title: 'Сосновая полка', price: 5000 },
];
createServer((req, res) => {
const url = new URL(req.url ?? '/', 'http://localhost');
if (url.pathname !== '/api/products') {
res.writeHead(404).end();
return;
}
const max = Number(url.searchParams.get('max') ?? Infinity);
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify(products.filter((p) => p.price <= max)));
}).listen(8082);
Go
Типизированные данные и маршрут с методом в шаблоне; результат — один бинарник.
package main
import (
"encoding/json"
"math"
"net/http"
"strconv"
)
type Product struct {
SKU string `json:"sku"`
Title string `json:"title"`
Price int `json:"price"`
}
var products = []Product{
{"A-100", "Дубовый стол", 24000},
{"B-200", "Сосновая полка", 5000},
}
// Go: один скомпилированный бинарник, каждый запрос обслуживается в своей горутине
func main() {
http.HandleFunc("GET /api/products", func(w http.ResponseWriter, r *http.Request) {
limit := math.MaxInt
if v, err := strconv.Atoi(r.URL.Query().Get("max")); err == nil {
limit = v
}
found := []Product{}
for _, p := range products {
if p.Price <= limit {
found = append(found, p)
}
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(found)
})
http.ListenAndServe(":8083", nil)
}
Частые ошибки при выборе бэкенда
-
Go для лендинга
Компилируемый сервис и VPS ради страницы с формой — больше эксплуатации, а выигрыша нет.
-
PHP для тысяч WebSocket
Модель запроса не подходит для долгих соединений без дополнительных инструментов.
-
Node.js для тяжёлых вычислений
Одно долгое вычисление останавливает все остальные запросы.
-
Выбирать по моде
Язык должен подходить задаче и команде, а не трендам года.
-
Один язык на всё
Небольшой сервис на Go рядом с сайтом на PHP часто решает нагрузку лучше, чем переписывание сайта.
-
Винить язык в проблемах базы
Большинство медленных бэкендов медленные из-за запросов и отсутствующих индексов, а не из-за языка.
Вопросы о PHP, Node.js и Go
Какой язык лучше для бэкенда?
Единого ответа нет: PHP — для сайтов и админок, Node.js — для реального времени и общего кода с фронтендом, Go — для нагрузки.
Какой самый быстрый?
Обычно Go, но для типичного сайта время уходит на базу, и все три достаточно быстры.
PHP хуже Node.js?
Нет, он другой: PHP проще и дешевле для сайтов, Node.js сильнее в реальном времени и общем коде.
Когда переходить с PHP на Go?
Не весь проект, а только ту часть, что не справляется с нагрузкой, — отдельным сервисом.
Можно ли их совмещать?
Да, и это частая схема: сайт на PHP, сервис на Go для нагрузки, Node.js для сборки фронтенда.
Что дешевле в хостинге?
PHP работает на любом виртуальном хостинге; Go расходует меньше всего памяти на VPS; Node.js нужен VPS или платформа.
Под что проще найти разработчиков?
PHP и Node.js — разработчиков очень много; Go — меньше, но обычно это сильные бэкенд-инженеры.
Форма
Подобрать
бэкенд
Работаю с PHP, Node.js и Go и выбираю по задаче: PHP для сайтов и админок, Go для сервисов под нагрузкой, Node.js там, где фронтенд и бэкенд делят код. Расскажите о проекте — отвечу в течение рабочего дня.