Node.JS [ru] | Серверный JavaScript
Node.js, backend и AI-разработка: статьи, новости, вайбкодинг, автоматизация и работа с ИИ-агентами. Личный блог автора - @just_genych По вопросам рекламы или разработки: @g_abashkin РКН: https://vk.cc/cJPGOP
Больше📈 Аналитический обзор Telegram-канала Node.JS [ru] | Серверный JavaScript
Канал Node.JS [ru] | Серверный JavaScript (@we_use_js) языкового сегмента Русский является активным участником. Сейчас сообщество объединяет 11 186 подписчиков, занимая 11 029 место в категории Технологии и приложения и 58 057 место в регионе Россия.
📊 Показатели аудитории и динамика
С момента создания невідомо проект демонстрирует стремительный рост, собрав аудиторию из 11 186 подписчиков.
Согласно последним данным от 09 июля, 2026, канал показывает стабильную активность. За последние 30 дней изменение числа участников составило -94, а за последние 24 часа — -9, при этом общий охват остаётся высоким.
- Статус верификации: Не верифицирован
- Уровень вовлечённости (ER): Средний показатель вовлечённости аудитории составляет 7.00%. В первые 24 часа после публикации контент обычно набирает 4.69% реакций от общего числа подписчиков.
- Охват публикаций: В среднем каждый пост получает 783 просмотров. В течение первых суток публикация набирает 525 просмотров.
- Реакции и взаимодействия: Аудитория активно поддерживает контент: среднее количество реакций на один пост — 2.
- Тематические интересы: Контент сосредоточен на ключевых темах, таких как node.js, javascript, node, process.exit(1, модуль.
📝 Описание и контентная политика
Автор описывает ресурс как площадку для выражения субъективного мнения:
“Node.js, backend и AI-разработка: статьи, новости, вайбкодинг, автоматизация и работа с ИИ-агентами.
Личный блог автора - @just_genych
По вопросам рекламы или разработки: @g_abashkin
РКН: https://vk.cc/cJPGOP”
Благодаря высокой частоте обновлений (последние данные получены 10 июля, 2026) канал поддерживает актуальность и высокий уровень охвата публикаций. Аналитика показывает, что аудитория активно взаимодействует с контентом, что делает его важной точкой влияния в категории Технологии и приложения.
Загрузка данных...
| Дата | Привлечение подписчиков | Упоминания | Каналы | |
| 10 июля | 0 | |||
| 09 июля | 0 | |||
| 08 июля | 0 | |||
| 07 июля | 0 | |||
| 06 июля | +1 | |||
| 05 июля | +2 | |||
| 04 июля | 0 | |||
| 03 июля | +2 | |||
| 02 июля | +3 | |||
| 01 июля | 0 |
| 2 | Грейсфул шатдаун: как SIGTERM и postMessage ломают порядок сигналов
Каждый middle/senior разработчик Node.js сталкивался с грейсфул шатдауном, но редкий замечает скрытую ловушку — смешивание process.on('SIGTERM') и Worker.prototype.postMessage. Из-за разницы приоритетов событий и микрозадач теряются данные в production.
Проблема приоритетов событий
SIGTERM — системное событие с высоким приоритетом в цикле событий. postMessage — асинхронная операция, попадающая в очередь микрозадач. Если SIGTERM приходит до завершения отправки сообщения, оно обрабатывается уже после shutdown. Результат — потеря данных, которые должны были уйти в Worker.
Production-пример и диагностика
Рассмотрим типичный код:
process.on('SIGTERM', () => {
console.log('Shutdown');
worker.terminate();
});
worker.postMessage({ type: 'data', payload: result });
Здесь postMessage может быть прерван сигналом. Как диагностировать:
* Логируйте порядок событий с таймстемпами.
* Используйте process.on('SIGTERM', { once: true }) для однократного вызова.
* Проверяйте флаг isShuttingDown перед любым postMessage.
Практическое исправление
Решение — флаги состояния:
let isShuttingDown = false;
process.on('SIGTERM', () => { isShuttingDown = true; });
if (!isShuttingDown) worker.postMessage({ ... });
Для надёжности — SharedArrayBuffer для атомарной синхронизации между основным потоком и Worker, если требуется строгий контроль.
Типичная ошибка
Многие путают: проблема не в доступе к process из Worker threads — Worker его не имеет. Корень — порядок микрозадач в основном потоке, где postMessage может быть отложен после обработки SIGTERM.
Вывод: Используйте флаги состояния перед асинхронными операциями в обработчиках сигналов — это предотвращает потерю данных при грейсфул шатдауне. | 383 |
| 3 | Прошла половина лета
Выгореть ещё успеем. А пока лето — отправляемся загорать.
И не просто так, а со скидкой 5000 рублей по промокоду NETSIL от Яндекс Путешествий.
Забронировать
#реклама
travel.yandex.ru
О рекламодателе | 447 |
| 4 | Маск внезапно выкатил Grok 4.5 — первую версию, заточенную под код и агентов 😨
Обучали её в связке с Cursor, и по бенчмаркам она уже перепрыгивает GPT-5.5, заодно держится на уровне Opus 4.8. Terminal-Bench: у неё 83%, а у Opus 4.8 — 78,9%.
Прайсинг: $2/$6 за миллион токенов. «Opus-уровень, но шустрее, меньше жрет токенов и дешевле» — написал Маск в X. В Cursor она уже есть на всех тарифах. Завтра ждем ответочку от Альтмана 😊
👉 Node.JS [ru] | 474 |
| 5 | 🔍Тестовое собеседование на Frontend-разработчика с ex. TeamLead в Сбер
9 июля(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Frontend-разработчика.
Как это будет:
📂 Даниил Дмитриев, старший разработчик в R-Vision, ex. TeamLead в Сбер, будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Даниил будет комментировать каждый ответ респондента, чтобы дать понять, чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Даниилу
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Frontend-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_front_bot
Реклама.
О рекламодателе. | 560 |
| 6 | Гео-аналитическая платформа вдвоём за 2,5 месяца: история spec-driven разработки
Автор поделился опытом старта проекта с чистого листа. Перед ним стояла амбициозная задача, не было легаси и была полная свобода выбора подхода. Он решил максимально довериться AI и больше не трогать код. Изначально были сомнения, что такой подход выдержит реальный масштаб, так как опыт подсказывал, что чем больше проект, тем быстрее AI путается в контексте и упирается в лимиты.
Через 2,5 месяца работы вдвоём удалось запустить гео-аналитическую платформу. Автор отмечает, что в до-AI эпоху такой проект строили бы годами. Этот опыт изменил его представление о разработке.
Читать далее | 520 |
| 7 | МТС Линк. Всё для коммуникации в команде
💻Платформа для общения, работы и обучения онлайн с поддержкой ИИ
Встречи, чаты и звонки в одном приложении
✅МТС Линк доступен в AppStore. Берите работу с собой и оставайтесь на связи с коллегами в любое время
Зарегистрироваться
#реклама 16+
mts-link.ru
О рекламодателе | 512 |
| 8 | Как один отказ бизнесу сэкономил компании 10 миллионов рублей
К концу проекта внедрения нового биллинга бизнес предложил перенести архивные продукты и исторические данные по ним. Архивные продукты использовались редко — для разбора спорных ситуаций с клиентами. Изначально было решено не избавляться от старого биллинга, а использовать его для чтения ретроданных. После оценки работ выяснилось, что типового механизма нет — нужно менять архитектуру, разрабатывать сценарии миграции, тестировать и поддерживать. Оценка составила около 10 миллионов рублей. Пересчет финансовой модели показал, что дополнительные инвестиции увеличивают срок окупаемости проекта на один год. Компания вкладывала бы деньги в функциональность без измеримой бизнес-ценности. Было принято решение отказать бизнесу и предложить оставить эти данные доступными для чтения в legacy биллинге.
Источник | 571 |
| 9 | Сидеть и работать в корпорации страшно, жизнь-то мимо проходит. Уходить строить бизнес страшно, а вдруг прогорит. Один из вариантов - разрабатывать свой пет-проект по вечерам. Многие успешные компании, например, Twitter, создавались именно так. Это не значит, что ваш проект обязательно заработает миллиарды, но заработать больше, чем в найме, и получить ценный опыт вполне реально.
Перед началом разработки появляется множество вопросов, например:
– Как выбрать идею для пет-проекта?
– Что нужно знать про маркетинг?
– Как запуститься и довести до первых продаж не имея бюджета на рекламу?
В телеграм-канале Твой пет проект, Михаил Табунов делится своим опытом с разработчиками и менеджерами.
Он рассказывает, где искать идею для нового проекта, что нужно знать о маркетинге, как запустить стартап и привлечь первых 10 клиентов, а также о многих других важных вещах.
Подписывайтесь на Твой пет проект получайте пользу от практиков рынка! | 563 |
| 10 | Онлайн-магистратура в ИТМО и МИФИ
Программы онлайн-магистратуры ИТМО и МИФИ в партнёрстве с Яндексом. Актуальные знания, практическое обучение и гибкий график. Учитесь, совмещая с работой. Доступна господдержка оплаты, отсрочка от армии
Перейти на сайт
#реклама 16+
practicum.yandex.ru
О рекламодателе | 584 |
| 11 | PROvoke на Analyst Days: как мы выступали в корсете и что из этого вышло
Привет, Хабр! В первой части я рассказывал, как мы с Татьяной Маркиной готовили доклад «Провоок» на Analyst Days — про споры, студию в Краснодаре, логистический ад и идею с кнутом и пряником. А сегодня — вторая часть: что произошло на сцене, какие роли мы играли, почему корсет так и не вышел в свет, и как один разговор в кулуарах перевернул моё понимание публичных выступлений. Подробности — во второй части статьи.
Источник: Анатомия парного доклада: как мы собирали «PROvoke» на Analyst Days. Часть 2 — выступление и фидбек | 629 |
| 12 | Выберите свой автомобиль Belgee на официальном сайте
Сочетание надёжности и комфорта. Широкий выбор комплектаций
Узнать больше
#реклама
belgee.ru
О рекламодателе | 595 |
| 13 | Buffer.write со str.length — тихая бомба под production.
Ты пишешь в буфер, передаёшь offset через str.length, и данные записываются в неверное место. Всё молча. Никаких ошибок. Просто битая информация.
В UTF-8 один символ может занимать от 1 до 4 байт. «Привет» — это 6 символов, но 12 байт. Если offset посчитан по длине строки, ты фактически говоришь Buffer: «запиши мне данные со смещением 6 байт». А нужно было с 12. Разница в два раза.
Я такое видел в production: кусок бинарного заголовка перезаписывался, файл читался как мусор. И никто не мог понять, почему.
Диагностика
— используй Buffer.byteLength(str, 'utf8') для вычисления реального размера в байтах;
— сравнивай str.length и Buffer.byteLength(str) — если различаются, в строке есть не-ASCII символы;
— проверяй логи, где размер буфера и смещение не сходятся.
Исправление
Простое решение:
const byteOffset = Buffer.byteLength(str, 'utf8');
buf.write(str, byteOffset);
Или вообще запиши с начала: buf.write(str, 0, 'utf8').
Типичная ошибка
— расчёт offset вручную через str.length * someCoefficient — это антипаттерн;
— молчаливое переполнение буфера без проверки остаточного места;
— путаница между символьным и байтовым смещением в одном бинарном сериализаторе.
Профилактика
— всегда считай байты через Buffer.byteLength();
— не вычисляй offset вручную для строк с Unicode;
— в TypeScript включай strict — он ловит часть таких косяков.
Вывод:
Silent data corruption — гадость редкая, но реальная. Проверь код: не используешь ли str.length как offset для Buffer.write? | 600 |
| 14 | Будьте в центре внимания — с Прайм-баннером
С новым медийным форматом Прайм-баннер вы можете не просто размещать рекламу на самых популярных сервисах Яндекса с высоким Brand Safety, а гибко управлять кампанией:
— Оптимизируйте стоимость размещения — формат доступен по аукционной модели без порога входа
— Настраивайте кросс-частоту и исключайте из показов неподходящие площадки
— Размещайтесь как на уже знакомых, так и на уникальных местах показа
— Выбирайте нужные среди более чем 600 таргетингов без наценок
— Оценивайте результаты с помощью исследований Brand Lift, Search Lift, Visit Lift и Target Lift
Узнайте больше о возможностях Прайм-баннера для вашего бренда.
Узнать больше
#реклама 16+
yandex.ru
О рекламодателе | 580 |
| 15 | Как я хакнул рынок труда: пишем свой ИИ-комбайн для автооткликов на HH.ru
Если вы хоть раз искали работу в IT за последний год, то знаете, что рынок беспощаден к новичкам. Нужно откликнуться на сотни вакансий, а в итоге получаешь отказы от роботов. Чтобы пробиться через фильтры HR, нужно под каждую вакансию писать уникальное сопроводительное письмо. В этой статье автор сделал полный разбор того, как написал собственного автономного ИИ-агента, который ищет вакансии, фильтрует мусор с помощью локальной нейросети, пишет персонализированные сопроводительные письма и отчитывается в Telegram, пока пользователь спокойно занимается своими делами. Скрипт задумывался бесплатным, автономным и не требующим настройки вокруг платных API.
Читать далее | 704 |
| 16 | Неявный deadlock в Node.js: AsyncLocalStorage + worker_threads + await в run()
Многие знают AsyncLocalStorage для проброса контекста, но скрещивание его с пулом worker_threads и await внутри колбэка run() создаёт неочевидный deadlock. Эта ошибка часто остаётся незамеченной до первого production-инцидента, когда пул потоков залипает при высокой нагрузке.
Как проявляется deadlock
Внутри run() вы помещаете ID запроса и вызываете await, пока воркер не закончит задачу. Если потоков в пуле ограниченное число (например, 2), а запросов много, каждый await блокирует run(), не освобождая поток из пула. Воркеры заняты, потоки ждут await — контекст AsyncLocalStorage не отпускается до полного завершения колбэка.
Пример problem:
const als = new AsyncLocalStorage();
async function processRequest(data) {
await als.run({ requestId: Date.now() }, async () => {
const worker = new Worker('./worker.js');
const result = await new Promise((resolve, reject) => {
worker.on('message', resolve);
worker.on('error', reject);
});
console.log(als.getStore().requestId);
});
}
Как обнаружить
- Залогируйте время выполнения воркеров: рост с увеличением числа запросов — тревожный сигнал.
- Используйте clinic.js или 0x: они покажут аномальные пики ожидания.
- Типичная ошибка: пул из 2 воркеров и 100 параллельных запросов — все зависнут через несколько секунд.
Практический совет
Не оставляйте await внутри run(). Вынесите ожидание наружу:
async function processRequest(data) {
const worker = new Worker('./worker.js');
const result = await new Promise(/*...*/);
als.run({ requestId: Date.now() }, () => {
console.log(als.getStore().requestId);
});
}
Либо передавайте контекст через worker.postMessage() — это проще и исключает deadlock.
Предупреждение
AsyncLocalStorage отлично работает на веб-серверах с краткими синхронными операциями, но await внутри run() с ограниченным пулом потоков — прямой путь к deadlock. Проверяйте такие места на этапе code review.
Вывод: Избегайте await внутри колбэка AsyncLocalStorage.run() при работе с пулом worker_threads — выносите асинхронное ожидание наружу или передавайте контекст через сообщения. | 632 |
| 17 | Диагностика и устранение неявной фрагментации кучи в Node.js
Long-lived HTTP серверы с разными по размеру payload часто страдают от "дырявой" кучи, хотя утечек памяти нет. Память фрагментируется из-за чередования маленьких и больших Buffer-ов, что ведет к росту RSS и частым GC паузам.
Как проявляется фрагментация
После обработки HTTP запросов создаются Buffer-ы разного размера: маленькие для заголовков, большие для тела. GC освобождает их неупорядоченно, оставляя пустоты между выделенными блоками. Со временем это увеличивает RSS на 20-40% без утечек. Симптомы: падение производительности через 12+' часов работы, частые stop-the-world паузы GC.
Диагностика в production
Первый шаг — трассировка с --trace-gc. Запустите: NODE_OPTIONS="--trace-gc" node app.js. В выводе ищите Mark-sweep паузы >50ms. Второй шаг — сравнение heapdump-ов через час и сутки работы в Chrome DevTools. Ищите фрагментированные объекты Buffer, разбросанные по куче. Третий шаг — проверьте флаги V8: node --v8-options | grep -i "heap.*frag".
Решение: Buffer Pool для однородности
Создайте пул Buffer-ов фиксированного сегмента, например 1024 байта. Это снижает разнообразие размеров и уменьшает фрагментацию. Пример:
class BufferPool {
constructor(size = 1024) {
this.pool = [];
this.size = size;
}
alloc(size) {
if (size > this.size) return Buffer.allocUnsafe(size);
if (this.pool.length) return this.pool.pop().slice(0, size);
return Buffer.allocUnsafe(this.size);
}
free(buf) { this.pool.push(buf); }
}
Практические советы и ошибки
- Для максимального снижения фрагментации используйте Buffer.allocUnsafeSlow вместо Buffer.allocUnsafe в пуле — он избегает shared memory pool.
- Настройте --max-old-space-size и --optimize-for-size для ограничения кучи.
- Типичная ошибка — использовать Buffer.allocUnsafe для всех случаев без разбора. Это увеличивает фрагментацию из-за случайных размеров.
- В Node 20+ можно изолировать тяжелые операции через --experimental-vm-modules в отдельных контекстах.
Вывод: Фрагментация кучи в long-lived серверах — реальная проблема, решаемая через Buffer Pool с фиксированным сегментом и контроль аллокаций, а не через поиск утечек. | 624 |
| 18 | Получи грант до 3,48 млн на обучение дизайну
Поступай на дизайн в Центральный университет с грантом.
Для учеников 10–11-х классов и СПО. Освой графический, UI/UX и продуктовый дизайн. Создавай визуальные концепты будущего.
На программе студенты получают фундаментальную базу, развивают прикладные навыки, приобретают опыт работы над реальными проектами, собирают портфолио и строят связи внутри дизайн-сообщества
Подать заявку
#реклама 16+
cu.ru
О рекламодателе | 491 |
| 19 | Скрытый убийца производительности: синхронный DNS в dns.lookup под нагрузкой
Высоконагруженный HTTP-клиент на Node.js внезапно теряет пропускную способность? Event loop залипает при большом количестве параллельных запросов? Чаще всего проблема не в HTTP, а в том, как система разрешает доменные имена.
В чем суть?
dns.lookup (используется http.request, https, axios по умолчанию) при вызове без флагов обращается к системному getaddrinfo через libuv. Этот вызов синхронный и блокирует event loop на время резолвинга. При 1000+ RPS latency одного разрешения (например, 50 мс) превращается в 50 000 мс общего блокирования цикла.
Как диагностировать?
1. Подключить dns.promises и выполнить dns.promises.lookup при нагрузке. Если event loop задерживает микротаски, виновник найден.
2. Использовать process.hrtime.bigint() до и после dns.lookup - разница > 10 мс системного времени указывает на проблему.
3. clinic doctor - на графике async latency видны ступеньки, совпадающие с пиками DNS-запросов.
Как устранить?
Для http(s) агентов - замена на асинхронный DNS:
const { createConnection } = require('net');
const dns = require('dns/promises');
const agent = new http.Agent({
createConnection: async (options, cb) => {
const { address } = await dns.lookup(options.hostname);
const socket = createConnection({ ...options, host: address });
cb(null, socket);
},
});
Типичная ошибка: использование только maxSockets или scheduling: 'lifo' снижает частоту новых соединений, но не решает первопричину при множестве уникальных хостов. Проще - библиотеки dns-cache или cacheable-lookup.
Вывод: блокировка из-за dns.lookup - классическая проблема одного потока Node.js на стыке системных вызовов, решается заменой на асинхронное разрешение через dns.promises или кастомный агент. | 671 |
| 20 | Диагностика и устранение гонок данных при конкурентном доступе к node:sqlite из worker_threads через in-memory WAL-режим
В production сценариях с worker_threads и in-memory SQLite в WAL режиме разработчики часто забывают синхронизировать доступ. Итог — SQLITE_BUSY, рассинхрон данных и дубли в уникальных полях.
Проблема: гонка без синхронизации
Несколько воркеров читают и пишут в одну in-memory базу без внешней координации. WAL помогает с параллельным чтением, но не спасает от гонок записи. Типичные проявления: ошибки SQLITE_BUSY, частичные обновления и потеря данных.
Решение: один писатель с явными блокировками
Выделите один воркер для критических записей (например, инкременты). Координируйте через SharedArrayBuffer и Atomics — это дешевле мьютексов. Воркеры-читатели используют отдельные соединения в WAL.
Production-oriented пример с BEGIN IMMEDIATE
Начиная с Node.js 23 используйте DatabaseSync. Обязательно PRAGMA journal_mode=WAL; и PRAGMA synchronous=NORMAL;:
import { DatabaseSync } from 'node:sqlite';
const db = new DatabaseSync(':memory:', { readwrite: true, create: true });
db.exec('PRAGMA journal_mode=WAL;');
db.exec('PRAGMA synchronous=NORMAL;');
function safeUpdate(sql) {
db.exec('BEGIN IMMEDIATE;');
try {
db.exec(sql);
db.exec('COMMIT;');
} catch {
db.exec('ROLLBACK;');
throw new Error('Write failed');
}
}
BEGIN IMMEDIATE блокирует запись сразу, избегая гонок. Без него два воркера могут начать транзакции одновременно — ловите SQLITE_BUSY.
Предупреждение: in-memory WAL не для продакшена
In-memory база теряет данные при краше. Для реальных проектов используйте файловую базу с WAL — это гарантирует персистентность.
Вывод: гонки данных в SQLite лечатся одним писателем и явными блокировками через BEGIN IMMEDIATE, давая скорость WAL без потери консистентности. | 675 |
