Развёртывание Express.js REST API на Render — пошаговое руководство

Этот материал покажет детально, как подготовить, настроить и развернуть Express.js REST API с использованием базы данных PostgreSQL на платформе Render. Руководство рассчитано на разработчиков среднего уровня: вы должны уметь работать с Node.js, npm и Git.
Важно: в конце 2022 года Heroku отменил бесплатный тариф. Render остаётся удобной альтернативой с бесплатным уровнем для небольших проектов, поэтому мы используем его в этом примере.
О чём этот гайд
- Как создать экземпляр PostgreSQL на Render (External/Internal URL).
- Как настроить локальную разработку с Knex и pg.
- Как подготовить миграцию для таблицы users.
- Как подключить репозиторий GitHub и задеплоить Web Service.
- Тестирование API в Postman.
- Рекомендации по безопасности, миграции и отказоустойчивости.
Что такое Render
Render — облачная платформа для хостинга веб-сайтов, приложений и баз данных. Она упрощает деплой, автоматически масштабирует и предоставляет интеграции с GitHub/GitLab.
Ключевые преимущества:
- Удобный интерфейс и интеграции с системами контроля версий.
- Встроенная поддержка баз данных (PostgreSQL, MySQL, MongoDB).
- Автоматические развёртывания и откаты.
- Поддержка кастомных доменов и бесплатных SSL-сертификатов.
Ограничения:
- Меньше гибкости для крайне специфичных сценариев по сравнению с управляемой инфраструктурой.
Сравнение Render и Heroku — кратко
- Простота: Render ориентирован на минимальную конфигурацию.
- Масштабирование: автоматическое масштабирование в зависимости от нагрузки.
- Стоимость: конкурентоспособные тарифы и бесплатный уровень для небольших проектов.
- Гибкость: для очень сложных систем может потребоваться более тонкая настройка на других платформах.
Подготовка: создание проекта и базы данных на Render
- Зарегистрируйтесь и войдите в аккаунт Render.
- На главной странице выберите создание новой базы данных: нажмите «New PostgreSQL».

- Укажите имя базы данных и нажмите Create database.
- Скопируйте Internal Database URL — он пригодится для подключения приложения, развёрнутого внутри Render. Если планируете подключаться с локальной машины до деплоя, используйте External Database URL.

Пояснение терминов:
- Internal Database URL — адрес для подключений с сервисов, размещённых на Render (внутренний сетевой маршрут).
- External Database URL — публичный адрес, пригоден для локальных подключений и внешних сервисов.
Совет: сначала создайте таблицы локально через External URL, затем в production укажите Internal URL.
Создаём Express.js REST API — структура проекта
Минимальная структура проекта:
- package.json
- index.js
- db.js
- /scripts/migrate.js
Установите зависимости:
npm install express pg knex(в исходнике примера использовались pg и knex; добавил express как обязательную зависимость).
Файлы и код
Создайте файл db.js в корне проекта и добавьте:
const knex = require('knex');
const db = knex({
client: 'pg',
connection: {
connectionString: 'the database URL',
ssl: {
rejectUnauthorized: false
}
}
});
module.exports = db;Пояснения:
- В production на Render замените ‘the database URL’ на Internal Database URL.
- Параметр ssl.rejectUnauthorized: false часто нужен при подключении к управляемым облачным базам, где TLS используется, но сертификат может не быть подписан тем же CA, что в локальной среде.
Откройте index.js и добавьте API:
const express = require("express");
const app = express()
const db = require('./db')
const PORT = process.env.PORT || 5000
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => res.send('Hello World!' ))
// Get all users
app.get('/users', async (req, res) => {
try {
const users = await db.select().from('users')
res.json(users)
} catch (error) {
console.error(error)
res.status(500).json({ message: 'Error retrieving users' })
}
})
app.post('/users', async (req, res) => {
try {
const user = await db('users').insert({ name: req.body.name }).returning('*')
res.json(user)
} catch (error) {
console.error(error)
res.status(500).json({ message: 'Error creating user' })
}
})
// Delete an existing user
app.delete('/users/:id', async (req, res) => {
try {
const { id } = req.params
const user = await db('users').where({ id }).delete().returning('*')
res.json(user)
} catch (error) {
console.error(error)
res.status(500).json({ message: 'Error deleting user' })
}
})
app.listen(PORT, () => console.log(`Server up at PORT:${PORT}`))Короткое объяснение маршрутов:
- GET /users — возвращает все записи из таблицы users.
- POST /users — добавляет запись с полем name и возвращает созданный объект.
- DELETE /users/:id — удаляет пользователя по id и возвращает удалённую запись.
Сценарий миграции: scripts/migrate.js
Создайте папку scripts и файл scripts/migrate.js:
const db = require('../db');
(async () => {
try {
await db.schema.dropTableIfExists('users')
await db.schema.withSchema('public').createTable('users', (table) => {
table.increments()
table.string('name')
})
console.log('Created users table!')
process.exit(0)
} catch (err) {
console.log(err)
process.exit(1)
}
})()Данная миграция создаёт таблицу users с автоинкрементным первичным ключом и полем name.
Обновите package.json scripts:
"scripts": {
"start": "node index.js",
"migrate": "node scripts/migrate.js"
}Перед запуском миграции убедитесь, что в db.js в connectionString стоит External Database URL, чтобы миграция подключалась из вашей локальной машины.
Запустите миграцию локально:
npm run migrateПосле удачного выполнения миграции можно переключить db.js на Internal Database URL перед деплоем на Render.
Развёртывание на Render: шаги
- Создайте репозиторий на GitHub и сделайте push проекта.
- Войдите в Render, нажмите New+ → Web Service.

- Подключите GitHub-репозиторий и выберите ветку для деплоя.

- На странице настроек сервиса укажите:
- Имя сервиса (например, my-express-api).
- Корневую директорию (если проект не в корне — настройте путь).
- Build command (если нужен сборочный шаг, например npm install).
- Start command: npm run start
- Нажмите Create Web Service и дождитесь окончания деплоя.
- После успешного развёртывания получите URL сервиса и протестируйте конечные точки.
Совет: задавайте переменные окружения (Environment → Environment → Add Environment Variable) в настройках Web Service вместо изменения db.js вручную. Например, добавьте DATABASE_URL и в db.js используйте process.env.DATABASE_URL.
Тестирование в Postman
- Сделайте POST на https://<ваш-сервис>.onrender.com/users с телом JSON:
{
"name": "Alice"
}- Сделайте GET на /users — вы должны увидеть созданную запись.


Практические советы по использованию Internal vs External URL
- Development локально: используйте External Database URL.
- Production на Render: используйте Internal Database URL или задайте DATABASE_URL как секретную переменную окружения в Web Service.
- Никогда не храните URL с паролем базы данных в репозитории. Используйте secrets/variables в Render.
Важно: смена URL после создания таблиц не повлияет на данные, если вы указываете один и тот же экземпляр базы. Internal/External — это лишь разные способы доступа к одному экземпляру.
Критерии приёмки
- API стартует без ошибок на Render и отвечает на GET /.
- POST /users создаёт запись и возвращает объект с id и name.
- GET /users возвращает список, включающий созданные записи.
- DELETE /users/:id удаляет запись и возвращает удалённый объект.
- Переменные окружения не содержат секретов в репозитории.
Роль-based чеклист перед деплоем
Для разработчика:
- Код проходит локальные тесты.
- package.json содержит корректные скрипты start и migrate.
- db.js использует process.env.DATABASE_URL.
Для DevOps/инженера релиза:
- В Render заданы переменные окружения (DATABASE_URL, NODE_ENV).
- TLS/SSL включены (Render делает это автоматически для доменов).
- Настроен резервный план бэкапа PostgreSQL (если критично).
Когда Render может не подойти (примеры)
- Если вам нужна тонкая настройка сети (частные VPC в специфичных конфигурациях).
- Если приложение требует специальных драйверов ОС или привязки к аппаратуре.
- Для экстремально высоких SLA и кастомной инфраструктуры может быть лучше управляемая облачная платформа типа AWS/GCP с собственными Terraform-скриптами.
Альтернативы
- Railway — простой процесс деплоя и бесплатный уровень для небольших проектов.
- Fly.io — удобен для edge-деплоя и геораспределённых сервисов.
- DigitalOcean App Platform — похож по функционалу, с другими ценовыми моделями.
Безопасность и приватность
- Не храните DATABASE_URL в коде. Используйте Secrets в Render.
- Включите SSL между приложением и базой (Render обычно использует TLS).
- Минимизируйте права учётной записи базы данных: выделите пользователя с доступом только к нужной схеме.
- В целях GDPR: если вы храните персональные данные, убедитесь в наличии правовой базы обработки и настройке резервного копирования и удаления данных по запросу.
Отказоустойчивость и мониторинг — рекомендации
- Включите логирование ошибок и сбор метрик (например, Sentry для ошибок).
- Настройте оповещения о падениях (Render поддерживает интеграции).
- Планируйте регулярные бэкапы базы данных и тестируйте восстановление.
Типичные ошибки и способы их исправления
- Ошибка подключения к базе (ECONNREFUSED/SSL): проверьте правильность DATABASE_URL и параметров ssl. Для Managed PostgreSQL часто нужен ssl: { rejectUnauthorized: false }.
- 502/503 после деплоя: проверьте стартовую команду и логи деплоя на Render.
- Миграция не создала таблицу: убедитесь, что миграция запускалась с правильным URL (External для локальной машины).
Мини-методология развёртывания (шаги)
- Локальная разработка и unit-тесты.
- Подготовка миграций и запуск на External URL.
- Подключение к GitHub и конфигурация Web Service на Render.
- Настройка переменных окружения (DATABASE_URL, NODE_ENV).
- Деплой и smoke-тесты (GET /, POST/GET /users).
- Включение мониторинга и бэкапов.
Шаблон: команда деплоя и переменные
- Build command: npm install –production
- Start command: npm run start
- Environment variable: DATABASE_URL — Internal Database URL (для production)
Примеры тестовых случаев / Acceptance criteria
- Тест 1: POST /users с телом {“name”:”Тест”} возвращает объект с id.
- Тест 2: GET /users возвращает массив, содержащий ранее добавленного пользователя.
- Тест 3: DELETE /users/:id удаляет пользователя и GET /users не возвращает его.
Короткая галерея крайних случаев
- Пустое имя при POST /users: сервис создаст запись с пустым name; добавьте валидацию на стороне сервера, если это недопустимо.
- Конкурентные вставки: при массовых параллельных запросах используйте транзакции или ограничения уникальности по бизнес-ключам.
- Большие payload: ограничьте размер запроса через express.json({ limit: ‘1mb’ }).
Часто задаваемые вопросы (FAQ)
Можно ли использовать Render бесплатно для небольшого проекта?
Да. Render предлагает бесплатный уровень для отдельных проектов. Ограничения могут меняться — проверяйте актуальные условия на сайте Render.
Как переключиться с External URL на Internal URL без потери данных?
Internal/External — способ доступа к одному экземпляру базы. После создания таблиц просто замените значения DATABASE_URL в настройках Web Service на Internal Database URL. Данные сохранятся.
Нужно ли использовать SSL для подключения к базе?
Да, рекомендуется. Managed базы обычно требуют TLS; параметр rejectUnauthorized: false часто используется для обхода проверки CA в облачных средах, но лучше настраивать доверенные сертификаты.
Социальная превью заготовка
OG Title: Развёртывание Express.js REST API на Render OG Description: Пошаговое руководство: PostgreSQL на Render, Knex, миграции, деплой через GitHub и тесты в Postman.
Резюме
- Render — удобная платформа для быстрого развёртывания приложений и баз данных с простым UI и интеграцией с GitHub.
- Рабочий процесс: настройка базы, локальные миграции через External URL, переключение на Internal URL для production и деплой Web Service.
- Не забывайте про безопасность: используйте переменные окружения и резервное копирование.
Дополнительные ресурсы: официальная документация Render и документация Knex/pg.
Похожие материалы
Лучшие виджеты для iPhone — обзор и инструкция
Темы WordPress: выбор, установка, управление
KVM на Arch Linux: установка и первая виртуальная машина
Эффект Зейгарник для продуктивности
Ремонт ноутбука: диагностика и практические советы