<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Febrian Notes]]></title><description><![CDATA[Febrian Notes]]></description><link>https://febrian-notes.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/6a6cb4116a146064bdf16afb/6ebe2025-5008-4498-8e4d-c8a02d5305a4.png</url><title>Febrian Notes</title><link>https://febrian-notes.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 31 Aug 2026 22:29:24 GMT</lastBuildDate><atom:link href="https://febrian-notes.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Dari Kode ke Production: Mengapa Deployment NestJS Tidak Harus Serumit Itu]]></title><description><![CDATA[Bagaimana saya mulai melihat deployment bukan hanya sebagai masalah infrastructure, tetapi juga sebagai bagian dari developer experience.
Sebagai developer, ada satu fase dalam pengembangan aplikasi y]]></description><link>https://febrian-notes.hashnode.dev/dari-kode-ke-production-mengapa-deployment-nestjs-tidak-harus-serumit-itu</link><guid isPermaLink="true">https://febrian-notes.hashnode.dev/dari-kode-ke-production-mengapa-deployment-nestjs-tidak-harus-serumit-itu</guid><category><![CDATA[nestjs]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[Devops]]></category><category><![CDATA[deployment]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[software development]]></category><category><![CDATA[backend]]></category><category><![CDATA[backend developments]]></category><category><![CDATA[opsctrl]]></category><dc:creator><![CDATA[Rachmat Febrian]]></dc:creator><pubDate>Fri, 14 Aug 2026 04:03:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a6cb4116a146064bdf16afb/3b0db004-8111-4300-b091-29cc43477145.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Bagaimana saya mulai melihat deployment bukan hanya sebagai masalah infrastructure, tetapi juga sebagai bagian dari developer experience.</strong></p>
<p>Sebagai developer, ada satu fase dalam pengembangan aplikasi yang sering terasa jauh lebih rumit daripada menulis kodenya sendiri: <strong>deployment</strong>.</p>
<p>Saat aplikasi masih berjalan di local environment, semuanya terasa sederhana.</p>
<p>Kita menjalankan:</p>
<pre><code class="language-plaintext">pnpm install
pnpm run start:dev
</code></pre>
<p>Kemudian aplikasi berjalan.</p>
<p>API bisa diakses. Database tersambung. Authentication bekerja. Semua terasa baik-baik saja.</p>
<p>Sampai akhirnya kita mengatakan:</p>
<blockquote>
<p>"Oke, sekarang kita deploy ke production."</p>
</blockquote>
<p>Dan di sinilah ceritanya mulai berbeda.</p>
<p>Tiba-tiba kita harus memikirkan Docker, environment variables, Node.js version, package manager, database, networking, DNS, CI/CD, secrets, logging, dan berbagai konfigurasi lain yang sebelumnya tidak terlalu terlihat.</p>
<p>Bagi saya, ini menarik karena menunjukkan bahwa menjadi software engineer bukan hanya tentang bagaimana membuat aplikasi bekerja.</p>
<p>Kita juga harus membuat aplikasi tersebut <strong>dapat berjalan dengan baik di environment yang berbeda dari komputer kita sendiri.</strong></p>
<p>Dan dari sinilah ketertarikan saya terhadap <strong>opsctrl</strong> dimulai.</p>
<hr />
<h2>Dari "Works on My Machine" ke Production</h2>
<p>Saya rasa hampir semua developer pernah mengalami situasi seperti ini.</p>
<p>Aplikasi berjalan sempurna di laptop.</p>
<p>Kemudian ketika dipindahkan ke server:</p>
<pre><code class="language-plaintext">It works locally.
It doesn't work in production.
</code></pre>
<p>Masalahnya bisa sangat sederhana.</p>
<p>Versi Node.js berbeda.</p>
<p>Package manager berbeda.</p>
<p>Environment variable belum tersedia.</p>
<p>Database configuration berbeda.</p>
<p>Atau sebuah dependency membutuhkan native binary yang tidak kompatibel dengan environment production.</p>
<p>Masalah-masalah seperti ini mungkin terlihat kecil secara individual.</p>
<p>Namun ketika semuanya muncul bersamaan, proses deployment bisa menjadi cukup kompleks.</p>
<p>Terutama ketika kita mulai menggunakan framework seperti NestJS yang biasanya berada di dalam ecosystem yang lebih besar.</p>
<p>Kita mungkin memiliki:</p>
<ul>
<li><p>NestJS application</p>
</li>
<li><p>PostgreSQL</p>
</li>
<li><p>Redis</p>
</li>
<li><p>background jobs</p>
</li>
<li><p>Docker</p>
</li>
<li><p>GitHub Actions</p>
</li>
<li><p>environment variables</p>
</li>
<li><p>domain</p>
</li>
<li><p>SSL</p>
</li>
<li><p>database migrations</p>
</li>
<li><p>monitoring</p>
</li>
<li><p>dan berbagai infrastructure lainnya.</p>
</li>
</ul>
<p>Aplikasi kita mungkin hanya terdiri dari beberapa module.</p>
<p>Tetapi infrastructure di belakangnya bisa jauh lebih besar.</p>
<hr />
<h2>NestJS Itu Mudah. Deployment-nya Bisa Berbeda Cerita</h2>
<p>Saya menyukai NestJS karena framework ini memberikan struktur yang cukup jelas untuk membangun backend application.</p>
<p>Dengan module, controller, service, guard, interceptor, dan berbagai abstraction lainnya, kita bisa membangun aplikasi yang relatif kompleks dengan struktur yang tetap terorganisir.</p>
<p>Tetapi setelah aplikasi selesai dibuat, pertanyaan berikutnya adalah:</p>
<blockquote>
<p>"Bagaimana aplikasi ini akan berjalan di production?"</p>
</blockquote>
<p>Misalnya kita menggunakan Docker.</p>
<p>Secara sederhana kita mungkin memiliki:</p>
<pre><code class="language-plaintext">FROM node:22-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

EXPOSE 3000

CMD ["node", "dist/main.js"]
</code></pre>
<p>Kelihatannya sederhana.</p>
<p>Tetapi production environment jarang sesederhana Dockerfile tersebut.</p>
<p>Kita mulai berhadapan dengan pertanyaan seperti:</p>
<ul>
<li><p>Apakah versi Node.js sesuai?</p>
</li>
<li><p>Apakah dependency dapat di-build di dalam container?</p>
</li>
<li><p>Apakah environment variable sudah tersedia?</p>
</li>
<li><p>Bagaimana database migration dijalankan?</p>
</li>
<li><p>Bagaimana aplikasi melakukan restart?</p>
</li>
<li><p>Bagaimana domain diarahkan ke application?</p>
</li>
<li><p>Bagaimana background worker dijalankan?</p>
</li>
<li><p>Bagaimana deployment dilakukan setiap kali ada perubahan di Git?</p>
</li>
</ul>
<p>Di titik ini, deployment mulai menjadi pekerjaan tersendiri.</p>
<hr />
<h2>Dependency Kecil Bisa Menjadi Masalah Besar</h2>
<p>Salah satu hal yang membuat saya semakin tertarik dengan problem deployment adalah bagaimana dependency yang terlihat sederhana dapat menjadi sumber masalah ketika environment berubah.</p>
<p>Contohnya adalah <code>bcrypt</code>.</p>
<p>Di local machine, kita mungkin hanya menjalankan:</p>
<pre><code class="language-plaintext">pnpm install
</code></pre>
<p>dan semuanya berjalan normal.</p>
<p>Tetapi ketika dependency tersebut harus dikompilasi di dalam Docker container, kondisi environment menjadi penting.</p>
<p>Operating system, architecture, Node.js version, package manager, bahkan C library yang digunakan oleh container dapat memengaruhi hasil akhirnya.</p>
<p>Salah satu contoh menarik adalah kombinasi <strong>pnpm 11, Docker, dan native dependencies seperti bcrypt</strong>.</p>
<p>pnpm 11 memperketat bagaimana build scripts dependency dijalankan. Jika konfigurasi tidak sesuai, proses install dapat berhenti. Tetapi menggunakan shortcut seperti <code>--ignore-scripts</code> juga bukan solusi yang benar untuk dependency yang memang membutuhkan proses compilation.</p>
<p>Masalahnya bahkan bisa berubah dari:</p>
<pre><code class="language-plaintext">Build failed
</code></pre>
<p>menjadi:</p>
<pre><code class="language-plaintext">Build succeeded
Runtime crashed
</code></pre>
<p>Dan menurut saya, yang kedua jauh lebih berbahaya.</p>
<p>Karena application terlihat berhasil di-deploy, tetapi kemudian gagal ketika fitur tertentu benar-benar digunakan.</p>
<p>Kasus seperti ini menunjukkan bahwa deployment bukan hanya masalah menjalankan <code>docker build</code>.</p>
<p>Kita harus memahami <strong>apa yang sebenarnya terjadi di balik proses tersebut</strong>.</p>
<hr />
<h2>Di Sini Opsctrl Menjadi Menarik</h2>
<p>Yang membuat saya tertarik dengan opsctrl bukan hanya ide bahwa deployment bisa dibuat lebih mudah.</p>
<p>Yang lebih menarik bagi saya adalah bagaimana kompleksitas infrastructure tersebut dapat diabstraksikan tanpa membuat developer sepenuhnya kehilangan konteks teknis.</p>
<p>Menurut saya, abstraction yang baik bukan berarti:</p>
<blockquote>
<p>"Developer tidak perlu tahu apa yang terjadi."</p>
</blockquote>
<p>Tetapi:</p>
<blockquote>
<p>"Developer tidak harus mengulang pekerjaan infrastructure yang sama setiap kali melakukan deployment."</p>
</blockquote>
<p>Ini perbedaan yang cukup penting.</p>
<p>Sebagai developer, kita tetap perlu memahami Docker.</p>
<p>Kita tetap perlu memahami database.</p>
<p>Kita tetap perlu memahami environment variables.</p>
<p>Kita tetap perlu memahami bagaimana application berjalan di production.</p>
<p>Tetapi kita tidak selalu ingin menghabiskan sebagian besar waktu kita hanya untuk menghubungkan semua bagian tersebut secara manual.</p>
<hr />
<h2>Developer Seharusnya Lebih Banyak Fokus pada Application</h2>
<p>Bayangkan workflow sederhana.</p>
<p>Kita sedang membangun REST API menggunakan NestJS.</p>
<p>Kita memiliki:</p>
<pre><code class="language-plaintext">NestJS API
    │
    ├── PostgreSQL
    │
    ├── Redis
    │
    └── Background Jobs
</code></pre>
<p>Secara application layer, kita ingin fokus pada hal-hal seperti:</p>
<pre><code class="language-plaintext">@Controller('users')
export class UsersController {
  @Get()
  findAll() {
    return this.usersService.findAll();
  }
}
</code></pre>
<p>Kita ingin memikirkan:</p>
<ul>
<li><p>bagaimana API bekerja,</p>
</li>
<li><p>bagaimana data diproses,</p>
</li>
<li><p>bagaimana authentication diterapkan,</p>
</li>
<li><p>bagaimana business logic dibuat,</p>
</li>
<li><p>dan bagaimana product memberikan value kepada user.</p>
</li>
</ul>
<p>Bukan menghabiskan waktu berjam-jam mengulang konfigurasi deployment yang sama.</p>
<p>Di sinilah menurut saya platform seperti opsctrl memiliki nilai.</p>
<p>Bukan karena infrastructure menjadi tidak penting.</p>
<p>Justru sebaliknya.</p>
<p>Infrastructure menjadi semakin penting sehingga kita membutuhkan tooling yang membantu developer mengelolanya dengan lebih konsisten.</p>
<hr />
<h2>Abstraction Bukan Berarti Menyembunyikan Infrastructure</h2>
<p>Ada satu hal yang menurut saya penting untuk dibicarakan.</p>
<p>Ketika kita menggunakan platform deployment, ada risiko developer menjadi terlalu bergantung pada abstraction.</p>
<p>Misalnya:</p>
<blockquote>
<p>"Saya tinggal klik deploy."</p>
</blockquote>
<p>Kemudian ketika sesuatu gagal, kita tidak tahu harus melakukan apa.</p>
<p>Menurut saya, itu bukan tujuan abstraction yang baik.</p>
<p>Platform yang baik seharusnya membuat developer <strong>lebih produktif tanpa membuat mereka kehilangan pemahaman teknis.</strong></p>
<p>Saya masih ingin tahu:</p>
<pre><code class="language-plaintext">Application
    ↓
Container
    ↓
Runtime
    ↓
Database
    ↓
Infrastructure
</code></pre>
<p>Tetapi saya tidak ingin setiap project baru memaksa saya mengulang seluruh konfigurasi dari awal.</p>
<p>Bagi saya, itulah salah satu hal yang menarik dari pendekatan opsctrl.</p>
<hr />
<h2>Kenapa Ini Relevan untuk Developer Indonesia?</h2>
<p>Saya juga tertarik melihat problem ini dari perspektif developer Indonesia.</p>
<p>Banyak developer memulai perjalanan mereka dengan frontend.</p>
<p>Kemudian belajar backend.</p>
<p>Kemudian mulai membuat API.</p>
<p>Kemudian menggunakan database.</p>
<p>Dan pada akhirnya mereka sampai pada satu pertanyaan:</p>
<blockquote>
<p>"Sekarang aplikasi saya mau di-deploy di mana?"</p>
</blockquote>
<p>Pada tahap tersebut, deployment bisa terasa seperti dunia baru.</p>
<p>Tiba-tiba muncul istilah seperti:</p>
<pre><code class="language-plaintext">Docker
CI/CD
Reverse Proxy
DNS
SSL
Container
Registry
Environment Variables
Database Migration
Worker
Queue
</code></pre>
<p>Bukan berarti developer tidak mampu mempelajarinya.</p>
<p>Tetapi learning curve-nya cukup besar.</p>
<p>Saya sendiri melihat ini sebagai salah satu area yang menarik dalam developer experience.</p>
<p>Semakin mudah seorang developer berpindah dari:</p>
<pre><code class="language-plaintext">Idea
  ↓
Code
  ↓
Application
  ↓
Production
</code></pre>
<p>semakin cepat mereka bisa memvalidasi ide dan membangun sesuatu yang benar-benar digunakan.</p>
<hr />
<h2>Deployment Seharusnya Membantu Developer Bergerak Lebih Cepat</h2>
<p>Pada akhirnya, tujuan deployment bukanlah deployment itu sendiri.</p>
<p>Tujuannya adalah membuat software bisa digunakan oleh orang lain.</p>
<p>Ini mungkin terdengar sederhana, tetapi menurut saya ini merupakan prinsip yang cukup penting.</p>
<p>Kita tidak membangun Docker image karena kita menyukai Docker.</p>
<p>Kita tidak mengkonfigurasi CI/CD hanya karena pipeline terlihat keren.</p>
<p>Kita melakukan semua itu karena kita ingin application kita dapat dikirim ke user dengan cara yang <strong>reliable, repeatable, dan predictable</strong>.</p>
<p>Dan semakin banyak infrastructure yang kita gunakan, semakin penting automation dan abstraction tersebut.</p>
<hr />
<h2>Yang Saya Pelajari dari Opsctrl</h2>
<p>Semakin saya mengenal opsctrl, semakin saya melihat deployment sebagai bagian dari <strong>developer experience</strong>, bukan hanya infrastructure.</p>
<p>Hal yang sebelumnya saya lihat sebagai pekerjaan terpisah:</p>
<pre><code class="language-plaintext">Code
Docker
Database
DNS
CI/CD
Deployment
</code></pre>
<p>sebenarnya merupakan bagian dari satu perjalanan:</p>
<pre><code class="language-plaintext">Developer
    ↓
Application
    ↓
Production
    ↓
User
</code></pre>
<p>Tools seperti opsctrl menarik bagi saya karena mencoba mengurangi friction di antara tahapan-tahapan tersebut.</p>
<p>Dan saya rasa ini menjadi semakin relevan ketika application yang kita bangun mulai berkembang.</p>
<p>Saat project masih kecil, kita mungkin bisa melakukan semuanya secara manual.</p>
<p>Tetapi ketika jumlah service, environment, deployment, dan developer bertambah, pendekatan manual mulai menjadi expensive.</p>
<p>Bukan hanya dalam bentuk uang.</p>
<p>Tetapi juga dalam bentuk:</p>
<ul>
<li><p>waktu,</p>
</li>
<li><p>complexity,</p>
</li>
<li><p>human error,</p>
</li>
<li><p>dan cognitive load.</p>
</li>
</ul>
<hr />
<p>Saya masih dalam proses mengenal lebih jauh bagaimana opsctrl bekerja dan bagaimana saya bisa berkontribusi di dalamnya.</p>
<p>Tetapi satu hal yang sudah cukup menarik perhatian saya adalah problem yang ingin diselesaikannya.</p>
<p>Sebagai developer, kita ingin membangun software.</p>
<p>Kita ingin menulis code.</p>
<p>Kita ingin membuat product.</p>
<p>Dan pada akhirnya, kita ingin user dapat menggunakan apa yang kita bangun.</p>
<p>Infrastructure tetap penting.</p>
<p>Deployment tetap penting.</p>
<p>Tetapi proses menuju production tidak seharusnya selalu menjadi sumber friction yang sama berulang kali.</p>
<p>Bagi saya, inilah alasan mengapa pendekatan seperti opsctrl menarik.</p>
<p>Bukan untuk menghilangkan infrastructure dari dunia developer.</p>
<p>Tetapi untuk membuat infrastructure <strong>lebih mudah dikelola, lebih repeatable, dan lebih dekat dengan workflow developer.</strong></p>
<p>Dan mungkin, bagi developer yang sedang berada di perjalanan yang sama seperti saya — dari sekadar membuat application sampai benar-benar menjalankannya di production — deployment bukanlah sesuatu yang harus ditakuti.</p>
<p>Deployment adalah bagian dari software engineering.</p>
<p>Dan semakin baik tools yang kita gunakan, semakin banyak energi yang bisa kita kembalikan kepada hal yang paling penting:</p>
<p><strong>building software.</strong></p>
]]></content:encoded></item></channel></rss>