Upgrade ke Node.js 26 LTS: Panduan Migrasi dan Cara Pakai Temporal API
Oleh Tim APIPedia, Tim Engineering APIPedia · Terbit · 9 menit baca
Node.js 26 resmi LTS sejak 28 Oktober 2026. Ikuti 5 langkah upgrade aman dan buat kalkulator SLA hari kerja dengan Temporal API.

Node.js 26 resmi menjadi rilis LTS (Long-Term Support) dengan codename "Lithium" lewat versi 26.13.0 pada 28 Oktober 2026. Artinya, versi ini kini aman dijadikan target production dan didukung sampai April 2029. Bonus terbesarnya: Temporal API, pengganti modern untuk Date, aktif tanpa flag.
Panduan ini fokus ke praktik. Kamu akan mengecek versi, memindai kode yang bakal rusak, memasang Node.js 26 berdampingan dengan versi lama, lalu menulis kalkulator tenggat SLA hari kerja dengan Temporal. Semua blok kode di bawah sudah kami jalankan di Node.js v26.13.0.
Apa yang berubah saat Node.js 26 naik ke LTS?
Node.js 26.0.0 dirilis 5 Mei 2026 sebagai rilis Current. Setelah sekitar enam bulan, jalur ini dipromosikan ke Active LTS. Menurut catatan rilis yang dirangkum linuxcompatible.org, versi 26.13.0 tidak membawa perubahan kode baru dibanding 26.12.1 selain metadata rilis seperti objek process.release. Jadi semua perbaikan keamanan di 26.12.1 (dirilis 21 Oktober 2026) ikut terbawa.
Hal penting yang perlu kamu tahu:
- Temporal aktif bawaan. Tidak perlu flag eksperimental lagi.
- V8 14.6 (dari Chromium 146), membawa
Map.prototype.getOrInsert()danIterator.concat(). - Undici 8 sebagai mesin
fetch()bawaan. Sumber menyebut 8.0.2 saat 26.0.0; di build 26.13.0 yang kami uji,process.versions.undicimelaporkan 8.12.2. - NODE_MODULE_VERSION 147, jadi semua add-on native harus dibangun ulang.
- API lama dihapus:
http.Server.prototype.writeHeader(), modul_stream_*, dan flag--experimental-transform-types. module.register()kini runtime-deprecated dan memunculkan warning.

Ada juga perubahan model rilis. Node.js 26 adalah jalur terakhir dengan model lama (dua major per tahun). Mulai 27.x, Node.js hanya merilis satu major per tahun di bulan April, naik LTS di bulan Oktober, dan setiap rilis akan menjadi LTS. Alpha Node.js 27 sudah muncul di indeks rilis resmi pada 29 Oktober 2026.
Versi mana yang sebaiknya dipakai sekarang?
| Jalur | Status (1 Nov 2026) | V8 | Akhir dukungan | Saran |
|---|---|---|---|---|
| Node.js 20 | EOL | - | 30 April 2026 | Segera pindah, tidak ada patch keamanan lagi |
| Node.js 22 "Jod" | Maintenance LTS | - | 30 April 2027 | Rencanakan migrasi dalam 6 bulan |
| Node.js 24 "Krypton" | LTS | - | April 2028 | Aman untuk production saat ini |
| Node.js 26 "Lithium" | Active LTS sejak 28 Okt 2026 | 14.6 | April 2029 | Target upgrade baru, jalankan dulu di CI |
| Node.js 27 | Alpha | 15.6 | April 2030 (rencana) | Hanya untuk eksperimen |
Catatan: tanggal EOL Node.js 24 hanya kami temukan di sumber sekunder, jadi cek ulang di halaman rilis resmi nodejs.org sebelum menyusun roadmap.
Langkah 1: Bagaimana cara mengecek versi dan status LTS?
Jalankan perintah berikut di mesin lokal atau server. Kolom lts berisi nama codename kalau build-nya LTS, dan undefined kalau masih Current.
node -v # v26.13.0
node -p "process.release.lts" # Lithium (undefined = bukan LTS)
node -p "process.versions.v8" # 14.6.202.34-node.40
node -p "process.versions.modules" # 147 -> ABI untuk add-on native
node -p "typeof Temporal" # object
Langkah 2: Apa yang perlu dipindai sebelum upgrade?
Penyebab paling umum aplikasi gagal jalan di Node.js 26 adalah API lama yang sudah dihapus. Pindai kode sendiri dan node_modules:
# Cari API yang dihapus di Node.js 26 (kode sendiri + dependensi)
grep -rnE "writeHeader\(|require\(['\"]_stream_|from ['\"]_stream_" \
--include='*.js' --include='*.cjs' --include='*.mjs' --include='*.ts' \
src/ node_modules/ 2>/dev/null | grep -v '\.d\.ts' | head -50
Kalau ada hasil, perbaikannya biasanya cuma satu baris:
// Sebelum (gagal di Node.js 26: writeHeader sudah dihapus)
res.writeHeader(200, { 'Content-Type': 'application/json' });
// Sesudah
res.writeHead(200, { 'Content-Type': 'application/json' });
// Sebelum
const Readable = require('_stream_readable');
// Sesudah
const { Readable } = require('node:stream');
Hasil di folder node_modules berarti dependensinya perlu diperbarui. Cek apakah versi terbaru paket itu sudah memperbaikinya sebelum menambal sendiri.
Langkah 3: Bagaimana memasang Node.js 26 tanpa mengganggu proyek lain?
Pakai version manager agar Node.js 24 dan 26 bisa hidup berdampingan. Yang sering terlupa: add-on native wajib dibangun ulang karena ABI naik ke 147.
# Pasang Node.js 26 di samping versi lama (nvm)
nvm install 26
nvm use 26
nvm alias default 26 # opsional, setelah semua test lolos
# Atau kunci versi per proyek
echo "26" > .nvmrc
# Add-on native (bcrypt, sharp, sqlite3, dll.) harus dibangun ulang untuk ABI 147
rm -rf node_modules
npm ci

Langkah 4: Bagaimana mulai memakai Temporal?
Date punya banyak jebakan: mutable, bulan dimulai dari 0, dan hanya mengenal zona lokal serta UTC. Temporal memecahnya menjadi tipe yang lebih tepat. Untuk tanggal jatuh tempo pakai PlainDate, untuk rapat lintas zona pakai ZonedDateTime, untuk timestamp log pakai Instant.

Simpan sebagai temporal-dasar.mjs lalu jalankan dengan node temporal-dasar.mjs:
// Waktu sekarang di Jakarta (WIB)
const now = Temporal.Now.zonedDateTimeISO('Asia/Jakarta');
console.log('Sekarang :', now.toString());
// Tanggal tanpa jam (cocok untuk tanggal jatuh tempo)
const tagihan = Temporal.PlainDate.from('2026-11-01');
const jatuhTempo = tagihan.add({ days: 30 });
console.log('Jatuh tempo:', jatuhTempo.toString(), '| hari ke-', jatuhTempo.dayOfWeek);
// Rapat jam 09.00 WIB, berapa jam di Tokyo dan London?
const rapat = Temporal.ZonedDateTime.from('2026-11-05T09:00[Asia/Jakarta]');
console.log('Tokyo :', rapat.withTimeZone('Asia/Tokyo').toPlainTime().toString());
console.log('London :', rapat.withTimeZone('Europe/London').toPlainTime().toString());
// Selisih dua tanggal dalam satuan yang jelas
const lts = Temporal.PlainDate.from('2026-10-28');
const eol = Temporal.PlainDate.from('2029-04-30');
console.log('Sisa dukungan:', lts.until(eol, { largestUnit: 'months' }).toString());
// Objek Temporal immutable: add() mengembalikan objek baru
console.log('Asli tetap:', tagihan.toString());
Contoh output di Node.js 26.13.0 (baris pertama tergantung jam saat dijalankan):
Sekarang : 2026-11-01T13:45:22.738763916+07:00[Asia/Jakarta]
Jatuh tempo: 2026-12-01 | hari ke- 2
Tokyo : 11:00:00
London : 02:00:00
Sisa dukungan: P30M2D
Asli tetap: 2026-11-01
Perhatikan dayOfWeek memakai angka 1 (Senin) sampai 7 (Minggu), tidak seperti getDay() yang mulai dari 0 di hari Minggu. Durasi P30M2D berarti 30 bulan 2 hari dalam format ISO 8601.
Satu peringatan untuk kode frontend: Temporal belum didukung Safari. Menurut lilting.ch, Chrome dan Edge 144+ serta Firefox 139+ sudah mendukung, dengan cakupan sekitar 69% browser. Di browser tetap pakai polyfill; di server Node.js 26 kamu bebas memakainya langsung.
Langkah 5: Fitur V8 baru apa yang langsung berguna?
Dua fitur kecil yang sering mempersingkat kode: getOrInsert untuk pola "ambil atau isi default" pada Map, dan Iterator.concat untuk menyambung beberapa iterable tanpa array perantara.
// Map.prototype.getOrInsert & getOrInsertComputed (proposal "upsert")
const hitung = new Map();
for (const kota of ['Bandung', 'Surabaya', 'Bandung']) {
hitung.set(kota, hitung.getOrInsert(kota, 0) + 1);
}
console.log(hitung); // Map(2) { 'Bandung' => 2, 'Surabaya' => 1 }
const cache = new Map();
const profil = cache.getOrInsertComputed('u-1', (id) => ({ id, dibuat: Date.now() }));
console.log(profil.id);
// Iterator.concat menyambung beberapa iterable tanpa membuat array perantara
const semua = Iterator.concat(['a', 'b'], new Set(['c']), ['d'].values());
console.log([...semua]); // [ 'a', 'b', 'c', 'd' ]
Proyek mini: menghitung tenggat SLA hari kerja
Kasus nyata di banyak aplikasi Indonesia: "tiket harus dibalas dalam 5 hari kerja". Hari kerja berarti melewati Sabtu, Minggu, libur nasional, dan cuti bersama. Temporal menangani aritmetika tanggal, sedangkan daftar libur resmi kita ambil dari API Hari Libur Nasional APIPedia (endpoint GET /v1/libur/tahun/{tahun}) yang mengikuti SKB tiga menteri.
// Hitung tenggat SLA "N hari kerja" dengan Temporal + API Hari Libur APIPedia
// Jalankan: APIPEDIA_KEY=apk_xxx node sla-hari-kerja.mjs 2026-12-21 5
const KEY = process.env.APIPEDIA_KEY;
const BASE = 'https://api.apipedia.id/v1/libur';
async function ambilLibur(tahun) {
const res = await fetch(`${BASE}/tahun/${tahun}`, {
headers: { Authorization: `Bearer ${KEY}` },
});
const json = await res.json();
if (!json.is_success) {
// Contoh: libur tahun depan belum ditetapkan SKB -> hitung akhir pekan saja
console.warn(`Peringatan: ${json.message}`);
return new Set();
}
return new Set(json.data.libur.map((l) => l.tanggal)); // libur nasional + cuti bersama
}
const cacheLibur = new Map();
async function isLibur(tanggal) {
const set = cacheLibur.get(tanggal.year) ?? (await ambilLibur(tanggal.year));
cacheLibur.set(tanggal.year, set);
return set.has(tanggal.toString());
}
async function tambahHariKerja(mulai, n) {
let t = Temporal.PlainDate.from(mulai);
let sisa = n;
while (sisa > 0) {
t = t.add({ days: 1 });
const akhirPekan = t.dayOfWeek >= 6; // 6 = Sabtu, 7 = Minggu
if (!akhirPekan && !(await isLibur(t))) sisa--;
}
return t;
}
const [mulai = Temporal.Now.plainDateISO('Asia/Jakarta').toString(), n = '3'] =
process.argv.slice(2);
const tenggat = await tambahHariKerja(mulai, Number(n));
console.log(`Mulai ${mulai} + ${n} hari kerja = ${tenggat} (${
tenggat.toLocaleString('id-ID', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })
})`);
Jalankan dengan API key dari console.apipedia.id:
APIPEDIA_KEY=apk_xxx node sla-hari-kerja.mjs 2026-12-21 5
# Mulai 2026-12-21 + 5 hari kerja = 2026-12-30 (Rabu, 30 Desember 2026)
Hasilnya benar: 24 Desember 2026 (cuti bersama Natal), 25 Desember (Natal), serta 26-27 Desember (akhir pekan) dilewati. Script ini sengaja tidak gagal ketika data tahun berikutnya belum ditetapkan SKB. Saat kami menguji, API mengembalikan pesan bahwa data 2027 belum tersedia, sehingga script hanya melewati akhir pekan. Konsekuensinya, 1 Januari 2027 ikut terhitung hari kerja. Untuk SLA lintas tahun, tambahkan daftar libur manual sampai SKB terbit.
Kalau hanya butuh jumlah hari kerja di antara dua tanggal, ada endpoint yang lebih ringkas: GET /v1/libur/hari-kerja?mulai=2026-12-01&sampai=2026-12-31. Hasilnya untuk Desember 2026: 31 hari, 21 hari kerja, 8 hari akhir pekan, dan 2 hari libur.
Bagaimana menjaga CI tetap aman selama transisi?
Jalankan test di dua versi sekaligus selama satu sprint. Flag --trace-deprecation membantu menemukan sumber warning seperti module.register().
# .github/workflows/test.yml
name: test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [24, 26]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: node --trace-deprecation --test
Setelah lolos, kunci versi minimum di package.json agar tim lain tidak tak sengaja memakai versi lama:
{
"engines": {
"node": ">=26.13.0"
}
}
Checklist singkat sebelum pindah production
node -p "process.release.lts"mengembalikanLithium.- Tidak ada hasil pindaian
writeHeader(dan_stream_. node_modulessudah dibangun ulang untuk ABI 147.- Test lolos di Node.js 24 dan 26 dan warning deprecation sudah ditinjau.
- Perilaku
fetch()(timeout, streaming, koneksi) sudah diuji di staging karena mesin Undici sudah naik ke versi 8. - Image Docker diganti ke tag
node:26dan diuji ulang.
FAQ
Apakah Node.js 26 sudah aman untuk production?
Ya, sejak 28 Oktober 2026 statusnya Active LTS. Tetap jalankan dulu di CI dan staging, terutama kalau aplikasimu memakai add-on native atau bergantung pada perilaku fetch().
Apakah saya wajib mengganti semua Date ke Temporal?
Tidak. Date tetap berfungsi. Mulailah dari bagian yang paling rawan bug: perhitungan jatuh tempo, zona waktu, dan durasi. Kode lama bisa dimigrasi bertahap.
Kenapa aplikasi saya error "Cannot find module '_stream_readable'"?
Modul internal _stream_* dihapus di Node.js 26. Ganti dengan require('node:stream'). Kalau error berasal dari dependensi, perbarui paket tersebut ke versi terbaru.
Masih pakai Node.js 20, apa risikonya?
Node.js 20 berakhir pada 30 April 2026 dan tidak lagi menerima perbaikan, termasuk perbaikan keamanan. Pindah ke Node.js 24 atau langsung ke 26.
Kapan Node.js 27 bisa dipakai?
Rencananya 27.0.0 rilis April 2027 dan naik LTS Oktober 2027. Saat ini versi alpha-nya hanya cocok untuk eksperimen.
Sumber
- Node.js: indeks rilis resmi (versi, tanggal, V8, npm, status LTS)
- Linux Compatible: Node.js 26.13.0 "Lithium" reaches LTS
- fireup.pro: Node.js 26 LTS, what's new and how to upgrade
- lilting.ch: Node.js 26 Current, Temporal dan Undici
- ecorpit: perubahan model rilis Node.js dan EOL Node.js 20
- Tech Insider: Node.js 22 vs 24 vs 26
Topik: #nodejs #javascript #temporal-api #tutorial #migrasi
Tentang penulis
Tim APIPedia — Tim Engineering APIPedia
Tim engineering di balik APIPedia yang membangun dan memelihara API data Indonesia - ongkir, OCR KTP, data wilayah, BMKG, hingga server MCP - dan menulis panduan integrasinya dari pengalaman langsung.