Найважливіше виправлення — перестати сприймати кожен таймаут Mongoose як проблему з налаштуванням таймауту. Повідомлення на кшталт MongoServerSelectionError: connection timed out зазвичай означає, що драйвер MongoDB не зміг обрати придатний сервер до закінчення часу serverSelectionTimeoutMS. У поточній документації з усунення несправностей MongoDB зазначено, що типовими причинами є проблеми з мережевим з'єднанням, обмеження доступу за IP в Atlas, збої DNS SRV та конфігурація TLS. Збільшення таймауту може змусити додаток чекати довше, не виправляючи жодної з цих умов.
Замість цього використовуйте такий порядок дій: 1) визначте, який саме таймаут спрацював, 2) переконайтеся, що хост додатка може отримати доступ до MongoDB, 3) виправте рядок з'єднання або адресу, специфічну для середовища, і 4) налаштовуйте значення таймаутів лише після того, як буде підтверджено працездатність з'єднання. Наведені нижче приклади використовують сучасні шаблони з'єднання Mongoose та поточну поведінку драйвера MongoDB, задокументовану у вересні 2026 року.
Спершу визначте, з яким саме таймаутом ви маєте справу
Mongoose використовує драйвер MongoDB для Node.js, тому в одній конфігурації з'єднання можуть зустрічатися різні налаштування таймаутів. Вони не означають одного й того ж.
| Налаштування або симптом | Що він контролює | Поточне задокументоване значення за замовчуванням | Типова інтерпретація |
serverSelectionTimeoutMS | Як довго драйвер намагається знайти придатний сервер MongoDB | 30 000 мс | Топологія, DNS, брандмауер, доступ за IP, недоступний сервер або відсутність придатного primary/secondary |
connectTimeoutMS | Як довго може тривати одна спроба встановлення TCP-з'єднання | 30 000 мс у поточному драйвері Node.js | Хост/порт недоступний, фільтрується або занадто повільний для встановлення TCP |
socketTimeoutMS | Як довго вже встановлене сокетне з'єднання може залишатися неактивним під час надсилання/отримання даних перед таймаутом | 0, що означає відсутність таймауту сокета в поточному драйвері Node.js | Зазвичай актуально після встановлення з'єднання, особливо для тривалих або завислих операцій |
ETIMEDOUT / таймаут з'єднання | Симптом збою на мережевому рівні | Не є значенням конфігурації за замовчуванням | Часто пов'язано з доступністю, брандмауером, маршрутизацією, ціллю DNS або недоступним сервером |
У поточній документації Mongoose щодо з'єднань зазначено, що значення serverSelectionTimeoutMS за замовчуванням становить 30 секунд і застосовується як до початкового виклику mongoose.connect(), так і до подальших операцій, які потребують вибору сервера. Документація драйвера MongoDB для Node.js щодо параметрів з'єднання розрізняє це значення від connectTimeoutMS та socketTimeoutMS.
Таймаут вибору сервера — це симптом, який слід класифікувати першим; деталі помилки та її первинна причина корисніші, ніж негайне збільшення 30-секундного ліміту.
Крок 1: захопіть точну помилку Mongoose та її первинну причину
Почніть з мінімального з'єднання та логування достатньої кількості інформації, щоб розрізнити збої DNS, автентифікації, TLS та доступності:
import mongoose from 'mongoose';
try {
await mongoose.connect(process.env.MONGODB_URI, {
serverSelectionTimeoutMS: 5000
});
console.log('MongoDB connected');
} catch (err) {
console.error(err);
console.error('Reason:', err.reason);
process.exit(1);
}
Значення 5 секунд вище є діагностичним вибором, а не рекомендацією для продакшену в кожному розгортанні. Mongoose зазначає, що зменшення serverSelectionTimeoutMS може забезпечити швидший зворотний зв'язок, але особливо застерігає від випадкового зменшення цього значення для наборів реплік, оскільки стандартне 30-секундне вікно може допомогти операціям пережити вибори та відмови. Mongoose радить коротші значення переважно для автономного MongoDB або безсерверних середовищ виконання, де швидка відмова є корисною.
Шукайте такі підказки:
getaddrinfo ENOTFOUND — не вдається розв'язати DNS-ім'я.
ECONNREFUSED — щось активно відхилило TCP-з'єднання, часто тому, що на хості/порті ніхто не очікує з'єднань.
ETIMEDOUT — спроба з'єднання не завершилася вчасно, часто через фільтрацію трафіку, неправильну маршрутизацію або недоступність призначення.
- Текст про TLS або сертифікати — перевірте довіру до сертифіката, відповідність імені хоста, підтримку протоколу або конфігурацію TLS.
- Помилки автентифікації всередині
err.reason — виправте облікові дані або authSource, а не змінюйте мережеві таймаути.
Умова: якщо помилка вже вказує на збій автентифікації, пропустіть налаштування брандмауера, доки облікові дані та база даних автентифікації не будуть правильними. Таймаут мережі та відхилений вхід — це різні класи збоїв.
Крок 2: перевірте мережу, доступ за IP в Atlas та DNS з того самого середовища виконання
Запускайте тести з'єднання з тієї ж машини, контейнера, віртуальної машини, безсерверної функції або пода Kubernetes, де працює процес Node.js. Тестування з вашого ноутбука недостатньо, якщо продакшен працює в іншому місці.
Для Atlas переконайтеся, що реальний вихідний IP додатка дозволений; для локального розгортання переконайтеся, що процес MongoDB дійсно очікує з'єднання на очікуваному інтерфейсі та порту.
Якщо ви використовуєте MongoDB Atlas
Atlas приймає з'єднання від клієнтів лише з адрес, дозволених у списку доступу за IP проєкту. MongoDB документує це в розділі Керування списком доступу за IP. Переконайтеся, що публічний вихідний IP середовища додатка доданий до списку, а не лише IP вашої особистої робочої станції.
У посібнику з усунення несправностей таймауту вибору сервера MongoDB також рекомендує перевіряти вихідну TCP-з'єднаність з MongoDB на порту 27017, а також брандмауери, групи безпеки, мережеві ACL, VPN та проксі-сервери.
Наприклад, з Linux або macOS ви можете перевірити конкретний вузол Atlas або керований вами хост за допомогою:
nc -vz your-mongodb-host.example.com 27017
У Windows PowerShell грубий тест доступності TCP виглядає так:
Test-NetConnection your-mongodb-host.example.com -Port 27017
Успішний тест TCP не гарантує успіху автентифікації або TLS, але невдалий тест TCP означає, що налаштування таймаутів Mongoose є передчасним.
Якщо ваш URI використовує mongodb+srv://
Рядок з'єднання SRV залежить від записів DNS SRV. Поточні кроки з усунення несправностей MongoDB рекомендують перевіряти пошук SRV з середовища клієнта:
nslookup -type=SRV _mongodb._tcp.cluster-name.mongodb.net
Якщо запит SRV не вдається, перевірте ім'я хоста та конфігурацію DNS. MongoDB документує рядок з'єднання mongodb:// без SRV як можливий обхідний шлях, коли середовище не може розв'язати записи SRV, але ви повинні отримати цей стандартний рядок з'єднання з Atlas або вашої конфігурації розгортання, а не вигадувати імена вузлів. Див. Усунення несправностей з'єднання в Atlas.
Правильна послідовність діагностики перевіряє адресу та мережевий шлях, перш ніж вважати значення таймаутів першопричиною.
Крок 3: виправте URI для середовища, де насправді працює Node.js
Синтаксично правильний URI MongoDB все ще може вказувати не туди. Перевірте схему, ім'я хоста, порт, ім'я бази даних, вимоги до набору реплік, джерело автентифікації та чи є ім'я хоста значущим у мережевому просторі імен додатка.
Локальний Node.js та локальний MongoDB
Mongoose наразі рекомендує використовувати 127.0.0.1 замість localhost для локального MongoDB:
await mongoose.connect('mongodb://127.0.0.1:27017/myapp');
Причина полягає в Node.js 18 та новіших версіях: Mongoose зазначає, що Node.js може розв'язати localhost в IPv6 ::1, тоді як локальний екземпляр MongoDB може очікувати з'єднання лише на IPv4. Mongoose також документує { family: 4 } як опцію, коли пріоритетне розв'язання IPv6 уповільнює спроби з'єднання:
await mongoose.connect('mongodb://localhost:27017/myapp', {
family: 4
});
Використовуйте family: 4 лише тоді, коли шлях розв'язання IPv4/IPv6 дійсно є проблемою. Якщо ваше розгортання MongoDB правильно підтримує IPv6, примусове використання IPv4 є непотрібним.
Node.js всередині Docker
Якщо додаток працює всередині контейнера, localhost посилається на цей контейнер, а не автоматично на MongoDB на хості або в іншому контейнері. Використовуйте ім'я хоста служби/контейнера MongoDB у спільній мережі Docker або специфічну для платформи адресу хоста, якщо MongoDB працює на хості.
Наприклад, для служби Compose з іменем mongo:
MONGODB_URI=mongodb://mongo:27017/myapp
Умова: цей приклад застосовний лише якщо контейнери спільно використовують мережу, а служба MongoDB дійсно називається mongo. Не копіюйте ім'я хоста в несумісне розгортання.
Atlas
Використовуйте рядок з'єднання, згенерований Atlas для вашого драйвера, збережіть хост mongodb+srv:// точно таким, закодуйте зарезервовані символи в іменах користувачів або паролях у форматі URL, якщо це необхідно, та переконайтеся, що користувач бази даних існує в потрібному проєкті.
Якщо ви підключаєтеся до керованого набору реплік, імена хостів, які повідомляє набір реплік, також мають бути доступними з клієнта. Початковий хост може бути доступним, але подальший вибір сервера все одно може зазнати невдачі, тому що члени набору реплік оголошують імена хостів, які додаток не може розв'язати або маршрутизувати.
Крок 4: налаштовуйте таймаути лише після успішного встановлення з'єднання
Якщо DNS розв'язується, мережевий шлях працює, сервер доступний, а URI правильний, тоді налаштування таймаутів стає змістовним.
Mongoose передає параметри з'єднання, пов'язані з таймаутами, базовому драйверу MongoDB, але кожен параметр контролює різний етап; більші значення не слід використовувати для приховування зламаної маршрутизації або недоступного сервера.
Консервативний приклад для додатка, який хоче отримати сигнал про невдачу протягом 10 секунд на початку, може виглядати так:
await mongoose.connect(process.env.MONGODB_URI, {
serverSelectionTimeoutMS: 10000,
connectTimeoutMS: 10000
});
Чи є 10 секунд доречним, залежить від розгортання. Компроміс є прямим:
| Вибір | Перевага | Компроміс | Де це може бути доречним |
| Коротший таймаут вибору сервера | Швидка відмова та швидший зворотний зв'язок при запуску | Менше часу на переживання тимчасових змін топології або виборів у наборі реплік | Розробка, перевірки стану, деякі шляхи запуску безсерверних додатків, автономний MongoDB |
| Стандартні 30 секунд | Більша толерантність до тимчасових порушень топології або мережі | Неправильна конфігурація може виявлятися протягом 30 секунд | Багато загальних продакшн-розгортань та набори реплік |
| Довший таймаут вибору сервера | Більше терпіння до незвично повільного відновлення | Запити та запуск можуть зависати довше перед відмовою | Лише коли виміряна поведінка відновлення виправдовує це |
Для socketTimeoutMS поточна документація драйвера MongoDB для Node.js використовує значення за замовчуванням 0, що означає відсутність таймауту неактивності сокета. MongoDB рекомендує, коли ви вирішуєте встановити це значення, обрати значення приблизно в два-три рази довші за найповільнішу операцію, яку ви очікуєте. Це налаштування застосовується до сокетів, які вже встановили з'єднання, тому воно не є основним виправленням для початкового таймауту вибору сервера.
Не копіюйте старі параметри з'єднання Mongoose у поточний проєкт
Багато старих прикладів все ще містять useNewUrlParser, useUnifiedTopology, keepAlive або keepAliveInitialDelay. Поточний Mongoose не потребує старих опцій парсера/топології, а Mongoose документує keepAlive як увімкнений за замовчуванням з Mongoose 5.2 та застарілий як параметр з'єднання з версії 7.2.
Сучасна базова конфігурація навмисно мінімальна:
import mongoose from 'mongoose';
await mongoose.connect(process.env.MONGODB_URI);
Додавайте параметри з'єднання тому, що ваше середовище їх потребує, а не тому, що вони з'явилися у фрагменті коду п'ятирічної давнини.
Що робити, якщо з'єднання працює, але запити пізніше завершуються таймаутом?
Це інша проблема. Якщо mongoose.connect() завершується успішно, а додаток пізніше зависає на запитах, дослідіть затримку операцій, тиск на пул з'єднань, навантаження сервера, індекси та таймаути сокетів або операцій. Поточний драйвер MongoDB для Node.js розрізняє:
serverSelectionTimeoutMS — пошук придатного сервера.
connectTimeoutMS — встановлення одного TCP-з'єднання.
socketTimeoutMS — неактивність на встановленому сокеті.
maxTimeMS — обмеження часу виконання операції на сервері після її досягнення MongoDB.
Якщо зазнають невдачі лише довгі запити, збільшення serverSelectionTimeoutMS навряд чи вирішить справжню проблему.
Швидка діагностика за умовою помилки
| Спостережувана умова | Найкорисніша наступна перевірка |
Server selection timed out after 30000 ms | Перевірте err.reason, потім протестуйте топологію, DNS, доступність TCP, список доступу Atlas та TLS |
getaddrinfo ENOTFOUND | Перевірте ім'я хоста та розв'язання DNS/SRV з середовища додатка |
ECONNREFUSED 127.0.0.1:27017 | Переконайтеся, що MongoDB запущена та очікує з'єднання на цій адресі/порту; у Docker перевірте, чи не встановлено ім'я хоста неправильно як localhost |
ETIMEDOUT | Перевірте брандмауер, маршрутизацію, групи безпеки, список дозволів IP, VPN/проксі та доступність сервера |
| Помилка рукостискання TLS або сертифіката | Виправте ланцюг довіри, ім'я хоста, сертифікат або підтримувану конфігурацію TLS; не вимикайте перевірку як виправлення для продакшену |
| Збій автентифікації | Виправте ім'я користувача, пароль, кодування URL, authSource або конфігурацію користувача бази даних |
Локальне з'єднання повільне з localhost | Спробуйте 127.0.0.1 або family: 4, якщо причиною є пріоритетне розв'язання IPv6 |
Шаблон з'єднання, придатний для продакшену
Тримайте секрети поза вихідним кодом, чітко повідомляйте про збій запуску, коли база даних недоступна, та логуєте достатньо деталей для діагностики без виведення облікових даних:
import mongoose from 'mongoose';
export async function connectDatabase() {
const uri = process.env.MONGODB_URI;
if (!uri) {
throw new Error('MONGODB_URI is not set');
}
try {
await mongoose.connect(uri, {
serverSelectionTimeoutMS: 30000,
connectTimeoutMS: 30000
});
console.log('MongoDB connected');
} catch (err) {
console.error('MongoDB connection failed:', err.message);
console.error('Server selection reason:', err.reason);
throw err;
}
}
Ці 30-секундні значення відповідають поточним задокументованим значенням за замовчуванням, тому ви можете опустити їх, якщо явне зазначення політики не допомагає вашим операціям. Важлива частина — не числа; важливо знати, чому інше число було б кращим для вашого розгортання.
Фінальний чек-лист
- Захопіть повну помилку та перевірте
err.reason.
- Переконайтеся, що розгортання MongoDB запущене та доступне.
- Запустіть тести DNS та TCP з того самого середовища, де працює процес Node.js.
- Для Atlas переконайтеся, що вихідний IP додатка доданий до списку доступу за IP.
- Для
mongodb+srv:// перевірте розв'язання DNS SRV.
- Для локального MongoDB спробуйте
127.0.0.1, якщо localhost розв'язується в непридатний IPv6.
- Для Docker або Kubernetes використовуйте ім'я хоста, яке є дійсним у цьому мережевому просторі імен.
- Виправляйте помилки TLS або автентифікації замість того, щоб маскувати їх більшим таймаутом.
- Налаштовуйте
serverSelectionTimeoutMS, connectTimeoutMS або socketTimeoutMS лише для етапу, який вони дійсно контролюють.
- Після виправлення переконайтеся, що додаток стабільно з'єднується з реального середовища розгортання, а не лише з ноутбука розробника.
Підсумок
Якщо Mongoose повідомляє про таймаут мережі MongoDB, спершу доведіть, що драйвер може виявити та отримати доступ до придатного сервера MongoDB. Обмеження IP в Atlas, брандмауери, розв'язання DNS SRV, неправильні імена хостів контейнерів, невідповідності IPv4/IPv6, недоступні процеси MongoDB та конфігурація TLS можуть створити враження, що 30-секундний таймаут є проблемою, хоча таймер лише повідомляє про збій.
Використовуйте налаштування таймаутів, щоб визначити, як довго ваш додаток має чекати на відому справну систему, а не для компенсації зламаної шляху з'єднання. Коли доступність мережі та URI правильні, обирайте значення таймаутів, які відповідають вашій моделі доступності, поведінці відмови та очікуваній затримці операцій.