<?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[Paudang | Software Architect & Node.js Expert]]></title><description><![CDATA[Technical blog of a Software Engineer focusing on Clean Architecture, Scalable Systems, and Node.js ecosystems. Home of the nodejs-quickstart-structure with 3,000+ downloads.]]></description><link>https://paudang.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/69a02d205fd4d31c613f5cd8/0b0ebb6b-33db-4b37-89d9-7bb08e2746aa.jpg</url><title>Paudang | Software Architect &amp; Node.js Expert</title><link>https://paudang.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 06 Sep 2026 06:04:33 GMT</lastBuildDate><atom:link href="https://paudang.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Art of Persistence: How I Built a Node.js Generator from Scratch and Reached the Global Tech Community]]></title><description><![CDATA[Three months ago, I made a choice that many developers consider "reinventing the wheel": I started building my own Node.js project generator.
But this wasn't about wheels. It was about foundations. Th]]></description><link>https://paudang.hashnode.dev/the-art-of-persistence-how-i-built-a-node-js-generator-from-scratch-and-reached-the-global-tech-community</link><guid isPermaLink="true">https://paudang.hashnode.dev/the-art-of-persistence-how-i-built-a-node-js-generator-from-scratch-and-reached-the-global-tech-community</guid><category><![CDATA[Node.js]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[Security]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Wed, 29 Apr 2026 17:53:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/d04c2ecb-8495-492d-9212-334ec18f76c0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Three months ago, I made a choice that many developers consider "reinventing the wheel": I started building my own Node.js project generator.</p>
<p>But this wasn't about wheels. It was about foundations. This is a reflection on a 90-day journey of "persistence"—moving from a local scratchpad to having my architectural insights published on <strong>System Weakness</strong> and reaching over 2,500 developers globally.</p>
<h2>The Problem: The "Running" Fallacy</h2>
<p>Most boilerplates in the Node.js ecosystem share a common flaw: they prioritize "getting it running" over "keeping it secure."</p>
<p>I grew weary of seeing production-level projects built on structures that leaked infrastructure details into the business logic. In many popular starters, the <strong>Security Ownership</strong> was fragmented, and the <strong>Core Domain</strong> was tightly coupled to specific database ORMs or framework-specific quirks.</p>
<p>I didn't want another "quick start." I wanted an <strong>Enterprise-Ready</strong> start.</p>
<h2>The Struggle: Auditing Every Line in Isolation</h2>
<p>The early days were solitary and, quite frankly, tedious. I spent weeks auditing every single line of code in <code>nodejs-quickstart-structure</code>.</p>
<p>My goal was strict <strong>Decoupling</strong>. I wanted a system where the business logic lived in a pure <strong>Core Domain</strong>, shielded from the <strong>Infrastructure Layer</strong> (the databases, external APIs, and even the web framework itself).</p>
<p>Development wasn't without its environmental hurdles. Dealing with WSL 2 on Windows presented its own set of "quirks" that tested my resolve. But these technical frictions were necessary; they forced me to ensure the generator was resilient across different developer environments.</p>
<h2>The Breakthrough: Rethinking Stateless Security</h2>
<p>The turning point wasn't a code commit, but a realization. While implementing JWT-based authentication, I realized that the industry's obsession with "statelessness" often comes at the cost of security—specifically, the difficulty of token revocation at scale.</p>
<p>I decided to write down my findings in a deep-dive analysis: <a href="https://systemweakness.com/the-illusion-of-stateless-security-rethinking-jwt-revocation-at-scale-8426472c5022">“The Illusion of Stateless Security: Rethinking JWT Revocation at Scale.”</a></p>
<p>This wasn't just a "how-to" guide. It was an architectural challenge to the status quo.</p>
<h2>The Achievement: Beyond the 2.5K Mark</h2>
<p>System Weakness is known for its rigorous editorial filter, often publishing only one or two deeply technical pieces a day. When my article was accepted and published, it felt like a validation of the "Clean Architecture" philosophy I had baked into the generator.</p>
<p>The numbers followed the quality:</p>
<ul>
<li><p><a href="https://systemweakness.com/the-illusion-of-stateless-security-rethinking-jwt-revocation-at-scale-8426472c5022"><strong>2.5K+ Views</strong></a> on the technical analysis.</p>
</li>
<li><p><a href="https://github.com/paudang/nodejs-quickstart-structure">3.1K+ Clones</a> of the repository on GitHub.</p>
</li>
</ul>
<p>Seeing developers from across the globe clone the structure I had built in my local WSL 2 environment was the ultimate proof of concept.</p>
<h2>The Lesson: "Good Wine Needs No Bush"</h2>
<p>There is an old saying: Good wine needs no bush.</p>
<p>If you build a product that solves a real architectural pain point, and if you write about it with enough depth and technical honesty, the world will eventually pay attention. You don't need a massive marketing budget; you need <strong>Persistence</strong> and <strong>Technical Integrity</strong>.</p>
<h2>What’s Next?</h2>
<p>The journey doesn't end here. The next milestone for <code>nodejs-quickstart-structure</code> is the implementation of a robust <strong>OAuth2 flow</strong>, further standardizing how we handle identity in modern applications.</p>
<p>If you believe that security and architecture shouldn't be afterthoughts, I’d love for you to join the movement. Check out the project, break it, and help us build a better "Day 0" for Node.js.</p>
<p><strong>Explore the project on GitHub:</strong> <a href="https://github.com/paudang/nodejs-quickstart-structure">paudang/nodejs-quickstart-structure</a></p>
<p><em>Pau Dang is the creator of Node.js Quickstart Structure and is on a mission to bring Enterprise-grade architecture to every developer's terminal.</em></p>
]]></content:encoded></item><item><title><![CDATA[Engineered for Speed: How I Built a 1:1 Parity Simulation for Node.js Project Scaffolding]]></title><description><![CDATA[One month ago, I released the first version of Node.js Quickstart Structure. It was a simple CLI tool born out of my own "Day 0" fatigue—the ritual of manually setting up directories, security, and CI]]></description><link>https://paudang.hashnode.dev/engineered-for-speed-how-i-built-a-1-1-parity-simulation-for-node-js-project-scaffolding</link><guid isPermaLink="true">https://paudang.hashnode.dev/engineered-for-speed-how-i-built-a-1-1-parity-simulation-for-node-js-project-scaffolding</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[architecture]]></category><category><![CDATA[Productivity]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Thu, 09 Apr 2026 08:50:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/a33a5115-ca8c-462c-b032-c391f7e09b8a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One month ago, I released the first version of <strong>Node.js Quickstart Structure</strong>. It was a simple CLI tool born out of my own "Day 0" fatigue—the ritual of manually setting up directories, security, and CI/CD for every new microservice.</p>
<p>After hitting <strong>4,000+ NPM downloads</strong> in 30 days, the community feedback was clear: the tool was powerful, but the "Question-Answer" CLI experience had limits.</p>
<p>For <strong>v2.0.0</strong>, I decided to build a <strong>Visual Web UI Configurator</strong>. But it wasn't just about making it pretty; it was a technical challenge of <strong>simulation parity</strong>.</p>
<p><a href="https://www.youtube.com/watch?v=Cxbb54T0uo8"><img src="https://img.shields.io/badge/YouTube-Video_Demo-red?style=for-the-badge&amp;logo=youtube&amp;logoColor=white" alt="YouTube" style="display:block;margin:0 auto" /></a></p>
<hr />
<h2>🛠️ The Challenge: 1,680+ Possible Combinations</h2>
<p>Our generator isn't a simple "Hello World" boilerplate. It supports:</p>
<ul>
<li><p><strong>Architectures</strong>: MVC vs. Clean Architecture.</p>
</li>
<li><p><strong>Languages</strong>: JavaScript vs. TypeScript (ESM).</p>
</li>
<li><p><strong>Communication</strong>: REST, GraphQL (Apollo), Kafka.</p>
</li>
<li><p><strong>Databases</strong>: MySQL, PostgreSQL, MongoDB.</p>
</li>
</ul>
<p>Mathematically, this results in over <strong>1,680+ project permutations</strong>. The real challenge for v2.0.0 was: <strong>How do I show the user exactly what they are getting in a browser sidebar before they even run a command?</strong></p>
<h2>🧠 Synchronizing Logic: app-setup.js vs. SimulationTree.vue</h2>
<p>To solve this, I had to ensure that the frontend simulation logic exactly matched the backend scaffolding logic.</p>
<p>Every folder in the UI is reactive. When a user toggles from "MVC" to "Clean Architecture," the entire hierarchy shifts. For instance, in our <strong>Clean Architecture</strong> scaffold, the <code>webserver</code> folder is exclusively for JavaScript, while TypeScript configurations are relocated to <code>src/config</code>.</p>
<h3>Technical Glimpse: Tree Logic</h3>
<p>Using Vue 3's reactive props, I built the <code>SimulationTree</code> component to handle conditional rendering based on the selected tech stack:</p>
<pre><code class="language-javascript">// A conceptual look at the Reactive Simulation Logic
const folders = computed(() =&gt; {
  return [
    {
      name: 'src',
      children: [
        { name: 'application', visible: props.architecture === 'Clean Architecture' },
        { name: 'infrastructure', visible: props.architecture === 'Clean Architecture' },
        { name: 'webserver', visible: props.architecture === 'Clean Architecture' &amp;&amp; props.language === 'JavaScript' },
        // ... and 1,680+ more condition checks
      ]
    }
  ];
});
</code></pre>
<p>This parity ensures that there are zero "surprises" when the user finally clones the repository.</p>
<h2>🏛️ Architecture: Empowering Choice</h2>
<p>Standardization shouldn't mean restriction. v2.0.0 empowers engineers to choose:</p>
<ul>
<li><p><strong>MVC</strong>: For velocity and rapid prototyping.</p>
</li>
<li><p><strong>Clean Architecture</strong>: For enterprise isolation and long-term maintainability.</p>
</li>
</ul>
<p>By automating the "boring stuff" like flyway migrations, multi-stage Dockerfiles, and Snyk security hardening, I allow developers to focus on the <strong>Business Domain</strong> from the first minute.</p>
<h2>🦾 AI-Native Experience: The .cursorrules Factor</h2>
<p>As someone who uses <strong>Cursor</strong> and other AI coding assistants daily, I realized that modern structure isn't just for humans—it's for LLMs.</p>
<p>Every project scaffolded by v2.0.0 includes a production-ready <code>.cursorrules</code> file. This acts as a "DNA Map" for AI agents, telling them exactly where business logic (domain) ends and delivery layers (interfaces) begin. This eliminates the "hallucination phase" where AI tries to guess your project's architecture.</p>
<h2>🗺️ What’s Next for the Movement?</h2>
<p>Reaching 4,000 developers was a signal that Node.js was missing a "Community Standard." with v2.0.0, we are one step closer to that.</p>
<p>👉 <strong>Experience the Simulation:</strong> <a href="https://nodejs-quickstart-generator.netlify.app/">Nodejs Quickstart Generator</a></p>
<p>⭐ <strong>Explore the Source Code:</strong> <a href="https://github.com/paudang/nodejs-quickstart-structure">GitHub Repository</a></p>
]]></content:encoded></item><item><title><![CDATA[Stop Shipping Vulnerabilities: How to Build 'Big Tech' Grade Node.js Apps in 2026]]></title><description><![CDATA[In the world of "Big Tech" (Google, Meta, Amazon), security isn't just a checkbox—it's non-negotiable. With over 90% of modern applications built on open-source dependencies, the risk of a "Supply Cha]]></description><link>https://paudang.hashnode.dev/stop-shipping-vulnerabilities-how-to-build-big-tech-grade-node-js-apps-in-2026</link><guid isPermaLink="true">https://paudang.hashnode.dev/stop-shipping-vulnerabilities-how-to-build-big-tech-grade-node-js-apps-in-2026</guid><category><![CDATA[Node.js]]></category><category><![CDATA[vulnerability]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[automation]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Fri, 27 Mar 2026 08:46:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/9f5beb20-8b0a-438e-b0e3-058833652a6b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the world of "Big Tech" (Google, Meta, Amazon), security isn't just a checkbox—it's <strong>non-negotiable</strong>. With over 90% of modern applications built on open-source dependencies, the risk of a "Supply Chain Attack" isn't a theory; it's an inevitability if you aren't prepared.</p>
<p>In this article, I’ll show you how to build an <strong>Automated Armor</strong> for your Node.js microservices using <strong>SCA</strong> and <strong>SAST</strong>, and how you can setup a zero-vulnerability baseline in under 5 minutes using the <a href="https://paudang.github.io/nodejs-quickstart-structure/">Node.js Quickstart Structure</a>.</p>
<hr />
<h2>🛑 The "Manual Review" Trap</h2>
<p>Many developers think code reviews are enough. But can your team manually audit 1,000+ nested <code>node_modules</code> every day? Probably not.</p>
<p>This is where automated tools like <strong>Snyk</strong> and <strong>SonarQube</strong> step in.</p>
<h3>🛡️ Snyk: Protecting your "Front Door" (SCA)</h3>
<p>Snyk scans your dependencies for known vulnerabilities. If a library you use (like <code>express</code> or <code>mongoose</code>) has a security flaw, Snyk detects it and even suggests the exact version to upgrade to.</p>
<h3>🔍 SonarQube/SonarCloud: The "Quality Gate" (SAST)</h3>
<p>While Snyk looks at external libraries, SonarQube looks at <strong>your code</strong>. It finds "Code Smells," bugs, and security hotspots (like SQL Injection patterns or hardcoded secrets) before they reach production.</p>
<hr />
<h2>🚀 Step-by-Step Security Setup</h2>
<p>Setting up these tools is often the hardest part, but I’ve built a generator that does 90% of the work for you. Here is how to get your environment ready:</p>
<h3>🛡️ 1. Snyk Integration (The Token)</h3>
<ol>
<li><p><strong>Create an Account</strong>: Sign up for free at <a href="https://snyk.io/">Snyk.io</a>.</p>
</li>
<li><p><strong>Get your Auth Token</strong>:</p>
<ul>
<li><p>Click your <strong>profile icon</strong> (bottom left) -&gt; <strong>Account Settings</strong>.</p>
</li>
<li><p>Find <strong>Auth Token</strong> and click "Click to show".</p>
</li>
</ul>
</li>
<li><p><strong>GitHub Secret</strong>: Add this as <code>SNYK_TOKEN</code> in your GitHub Repository Settings -&gt; Secrets.</p>
</li>
</ol>
<h3>🔍 2. SonarCloud Integration (Organization &amp; Host)</h3>
<p>SonarCloud is the SaaS version of SonarQube. It's free for public projects!</p>
<ol>
<li><p><strong>Login</strong>: Use your GitHub account at <a href="https://sonarcloud.io/">SonarCloud.io</a>.</p>
</li>
<li><p><strong>Import Project</strong>: Click the <strong>"+"</strong> icon (top right) -&gt; <strong>Analyze new project</strong>. Import your repository.</p>
</li>
<li><p><strong>Disable Automatic Analysis</strong>: Go to <strong>Administration -&gt; Analysis Method</strong> and turn <strong>OFF</strong> Automatic Analysis. Select <strong>GitHub Actions</strong> instead.</p>
</li>
<li><p><strong>Get your Details</strong>:</p>
<ul>
<li><p><strong>Project Key</strong>: Usually <code>your-org_your-repo</code>. Find it on the project dashboard.</p>
</li>
<li><p><strong>Organization Key</strong>: Your username or organization name.</p>
</li>
<li><p><strong>SONAR_HOST_URL</strong>: For the cloud version, this is always <code>https://sonarcloud.io</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Token</strong>: Go to <strong>My Account -&gt; Security -&gt; Generate Token</strong>. Add it as <code>SONAR_TOKEN</code> in GitHub Secrets.</p>
</li>
</ol>
<hr />
<h2>🏗️ Demo: Zero-Vulnerability Projects</h2>
<p>If you want a project that comes with these tools <strong>pre-configured</strong>, you can use the <code>nodejs-quickstart-structure</code>:</p>
<pre><code class="language-bash">npx nodejs-quickstart-structure@latest init
</code></pre>
<p>When prompted for <strong>Enterprise Security Hardening</strong>, select <strong>"Yes"</strong>.</p>
<p>It will automatically generate:</p>
<ul>
<li><p>🐳 <strong>Hardened Dockerfile</strong>: Using <code>node:22.22.2-trixie-slim</code> (The gold standard for security).</p>
</li>
<li><p>🔄 <strong>CI/CD Pipelines</strong>: Pre-built workflows for GitHub Actions, GitLab, and Jenkins.</p>
</li>
<li><p>🐕 <strong>Husky Hooks</strong>: Automated linting and formatting before every commit.</p>
</li>
</ul>
<hr />
<h2>💡 The Takeaway: Security is a Feature, Not a Chore</h2>
<p>Automating security audits isn't just about finding bugs; it's about <strong>Engineering Excellence</strong>. By shifting security "Left" into your dev environment, you catch issues early, save thousands in technical debt, and deploy with the confidence of an elite engineer.</p>
<p><strong>Ready to upgrade your workflow?</strong></p>
<ol>
<li><p><strong>Try the Generator</strong>: <a href="https://github.com/paudang/nodejs-quickstart-structure">nodejs-quickstart-structure</a></p>
</li>
<li><p><strong>Read the Full Guide</strong>: <a href="https://paudang.github.io/nodejs-quickstart-structure/guide/security-hardening">Enterprise Security Setup</a></p>
</li>
<li><p><strong>Star the project</strong> on GitHub if this helps your team! ⭐️</p>
</li>
</ol>
<p><em>Have you encountered a major security flaw in your dependencies recently? Let's discuss in the comments below!</em></p>
]]></content:encoded></item><item><title><![CDATA[How I Built a Node.js CLI to Scaffold Automated E2E Testing Infrastructure (Postgres, Kafka, Redis)]]></title><description><![CDATA[If you've ever scaffolded a new Node.js microservice, you know the pain: setting up Express/Fastify is easy, but wiring up the real infrastructure—PostgreSQL, Redis, Kafka, and an ironclad End-to-End ]]></description><link>https://paudang.hashnode.dev/how-i-built-a-node-js-cli-to-scaffold-automated-e2e-testing-infrastructure-postgres-kafka-redis</link><guid isPermaLink="true">https://paudang.hashnode.dev/how-i-built-a-node-js-cli-to-scaffold-automated-e2e-testing-infrastructure-postgres-kafka-redis</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Testing]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Microservices]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Wed, 25 Mar 2026 18:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/bef157de-d645-48a9-aa3f-46fabcb78aef.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've ever scaffolded a new Node.js microservice, you know the pain: setting up Express/Fastify is easy, but wiring up the <strong>real infrastructure</strong>—PostgreSQL, Redis, Kafka, and an ironclad End-to-End (E2E) testing framework—takes days of repetitive boilerplate.</p>
<p>As a backend engineer, I got tired of manually configuring <code>docker-compose.yml</code>, fighting with Jest timeouts, and debugging Kafka network issues. That’s why I decided to build-in-public and open-source my own ultimate generator: <code>nodejs-quickstart-structure</code>.</p>
<p>In this article, I want to take you behind the scenes of how I engineered the CLI to automatically generate <strong>100% Deterministic E2E Testing Infrastructures</strong> out of the box.</p>
<hr />
<h2>1. The Goal: A "Zero-Config" Production Setup</h2>
<p>My vision for the CLI was simple: When a developer runs <code>npx nodejs-quickstart init</code> and selects <em>TypeScript, PostgreSQL, Kafka, and Redis</em>, the generated repository shouldn't just contain empty controller files. It must include a fully automated testing pipeline that <em>actually tests the integration of these services</em>.</p>
<p>To achieve this, the CLI needed to solve three major challenges:</p>
<ol>
<li><p>Isolating Unit Tests from E2E Tests.</p>
</li>
<li><p>Automating the Docker lifecycle during testing.</p>
</li>
<li><p>Solving the dreaded "Kafka Host vs Container" networking issue.</p>
</li>
</ol>
<hr />
<h2>2. Challenge #1: Isolating the Test Environments</h2>
<p>Most generic templates dump everything into one <code>jest.config.js</code>. This leads to the infamous "flaky tests" where developers accidentally use their local development database state for E2E tests, or where heavy integration tests slow down local unit test execution.</p>
<p><strong>How the CLI solves this:</strong> During the scaffolding process, the CLI uses EJS templates to physically separate configurations. It generates two distinct files:</p>
<ul>
<li><p><code>jest.config.js</code>: Strictly for Unit tests (milliseconds execution, everything mocked).</p>
</li>
<li><p><code>jest.e2e.config.js</code>: Designed for heavy lifting. It safely ignores <code>node_modules</code>, specifically targets the <code>tests/e2e</code> directory, and extends the <code>testTimeout</code> to 30,000ms to allow Docker dependencies to boot.</p>
</li>
</ul>
<pre><code class="language-javascript">// Automatically generated jest.e2e.config.js
module.exports = {
  ...require('./jest.config'),
  testMatch: ['&lt;rootDir&gt;/tests/e2e/**/*.test.ts', '&lt;rootDir&gt;/tests/e2e/**/*.test.js'],
  testTimeout: 30000,
  clearMocks: true
};
</code></pre>
<hr />
<h2>3. Challenge #2: The Automated Docker Lifecycle</h2>
<p>A true E2E test shouldn't require the developer to manually orchestrate infrastructure. I wanted the command <code>npm run test:e2e</code> to be a magic bullet.</p>
<p>To achieve this, the CLI injects a custom Node.js script (<code>scripts/run-e2e.js</code>) into the generated project. Here is the magic workflow it executes:</p>
<ol>
<li><p><strong>Assigns a Testing Port:</strong> It overrides <code>process.env.PORT = '3001'</code> so E2E tests never collide with the developer's running dev server on <code>3000</code>.</p>
</li>
<li><p><strong>Boots Infrastructure:</strong> Executes <code>docker-compose up -d db redis kafka</code>.</p>
</li>
<li><p><strong>Health Checking:</strong> It uses the <code>wait-on</code> library to constantly poll <code>http-get://127.0.0.1:3001/health</code> until the Node.js application confirms all database migrations and Kafka broker connections are successful.</p>
</li>
<li><p><strong>Executes Jest:</strong> Runs the rigorous E2E assertions.</p>
</li>
<li><p><strong>Graceful Teardown:</strong> Executes <code>docker-compose down</code> to sweep away the testing infrastructure, leaving the developer's machine spotless.</p>
</li>
</ol>
<hr />
<h2>4. Challenge #3: The Kafka Networking Nightmare</h2>
<p>If you’ve ever tried to run a Node.js test runner on your local host while Kafka sits inside a Docker bridged network, you've likely seen this error: <code>getaddrinfo ENOTFOUND kafka</code></p>
<p>This happens because the <code>kafkajs</code> client connects to the Docker mapped port, asks for the cluster metadata, and Kafka responds: <em>"Hi, I am the leader, my address is</em> <code>kafka:9092</code><em>!"</em>. The host machine has no idea what <code>kafka</code> is, so it crashes.</p>
<p><strong>How the CLI fixes this for you:</strong> The CLI expertly scaffolds the <code>docker-compose.yml</code> to utilize <strong>KRAFT mode</strong> and explicitly maps a secondary <code>PLAINTEXT_HOST</code> listener strictly for your host tests.</p>
<pre><code class="language-yaml"># Generated by nodejs-quickstart
kafka:
  image: bitnamilegacy/kafka
  ports:
    - "9093:9093" # Exposed safely for Host testing
  environment:
    - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:9093
    - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,PLAINTEXT_HOST://:9093,CONTROLLER://:9094
</code></pre>
<p>It then automatically points your <code>.env.test</code> Kafka Broker string to <code>localhost:9093</code>. The result? Seamless local testing with zero networking headaches.</p>
<hr />
<h2>5. Try it out!</h2>
<p>Building tools for other developers is arguably one of the most rewarding challenges in software engineering. By standardizing these elite testing configurations, we can eliminate flaky tests across hundreds of new projects.</p>
<p>If you are starting a new Node.js microservice, don't waste 3 days configuring Jest, Docker, and Kafka manually. Give the CLI a spin:</p>
<pre><code class="language-bash">npx nodejs-quickstart-structure init
</code></pre>
<p>Check out the full open-source repository here:<br />👉 <a href="https://github.com/paudang/nodejs-quickstart-structure">GitHub - nodejs-quickstart-structure</a></p>
<p><strong>Have you ever struggled with Dockerizing your E2E tests? Let me know your biggest pain points in the comments! 👇</strong></p>
]]></content:encoded></item><item><title><![CDATA[Master Caching Patterns: A Clean Architecture Guide with AI-Native Tooling]]></title><description><![CDATA[In high-performance systems, caching is the ultimate "lifesaver" for reducing database load and optimizing response times. However, choosing the right pattern (Cache-Aside, Write-Through, etc.) depend]]></description><link>https://paudang.hashnode.dev/master-caching-patterns-a-clean-architecture-guide-with-ai-native-tooling</link><guid isPermaLink="true">https://paudang.hashnode.dev/master-caching-patterns-a-clean-architecture-guide-with-ai-native-tooling</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Clean Architecture]]></category><category><![CDATA[caching]]></category><category><![CDATA[backend]]></category><category><![CDATA[software architecture]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Sun, 22 Mar 2026 01:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/75789101-75aa-4f0d-84d2-92059ba7873e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In high-performance systems, caching is the ultimate "lifesaver" for reducing database load and optimizing response times. However, choosing the right pattern (Cache-Aside, Write-Through, etc.) depends heavily on your specific use case. In this article, I’ll walk you through a hands-on demo project that showcases 5 essential caching patterns, built with <strong>Clean Architecture</strong> and the power of an AI-Native tool: <strong>nodejs-quickstart-structure</strong>.</p>
<hr />
<h2>Why Caching?</h2>
<p>When scaling applications, the database often becomes the bottleneck. Caching strategically places frequently accessed data in memory (like Redis) to bypass slow disk I/O. But not all caching is equal. To understand the nuances, I built a showcase service from scratch.</p>
<p>To skip the boilerplate and focus on the patterns, I used <a href="https://github.com/paudang/nodejs-quickstart-structure">nodejs-quickstart-structure</a>, a CLI tool designed for AI-ready, structured development.</p>
<hr />
<h2>5 Caching Patterns You Must Know</h2>
<p>Here is a breakdown of the 5 patterns implemented in this demo:</p>
<h3>1. Cache-Aside (Lazy Loading)</h3>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2v6nge0uosjc2ljij9r.png" alt="Image description" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Purpose</strong>: The application manages the cache. Data is only loaded into the cache when specifically requested.</p>
</li>
<li><p><strong>When to use</strong>: Best for systems with <strong>Read &gt;&gt; Write</strong> ratios (e.g., User Profiles).</p>
</li>
<li><p><strong>Pros</strong>: Memory efficiency; cache only contains data that is actually needed.</p>
</li>
</ul>
<h3>2. Read-Through</h3>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ix6mhsj30nhr3wi96hf3.png" alt="Image description" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Purpose</strong>: Offloads data-fetching logic to the Cache Provider. The app simply calls "Get" from the cache.</p>
</li>
<li><p><strong>When to use</strong>: To keep the business logic (Use Case) clean and decouple from the database.</p>
</li>
<li><p><strong>Pros</strong>: Extremely clean business code.</p>
</li>
</ul>
<h3>3. Write-Through</h3>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/62niw25r5y4p49hscguz.png" alt="Image description" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Purpose</strong>: Data is written to both the Cache and the Database simultaneously.</p>
</li>
<li><p><strong>When to use</strong>: When <strong>Strong Consistency</strong> is required.</p>
</li>
<li><p><strong>Pros</strong>: Minimal data inconsistency risk.</p>
</li>
</ul>
<h3>4. Write-Around</h3>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/urat61ubxcq86ujstqzi.png" alt="Image description" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Purpose</strong>: Data is written directly to the DB, and the corresponding cache entry is invalidated (deleted).</p>
</li>
<li><p><strong>When to use</strong>: When the written data might not be read again immediately.</p>
</li>
<li><p><strong>Pros</strong>: Prevents "polluting" the cache with data that won't be reused soon.</p>
</li>
</ul>
<h3>5. Write-Back (Write-Behind)</h3>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5po6m7z4ljybcv4xxnol.png" alt="Image description" style="display:block;margin:0 auto" />

<ul>
<li><p><strong>Purpose</strong>: Data is written to the Cache first; the DB update happens asynchronously in the background.</p>
</li>
<li><p><strong>When to use</strong>: For <strong>exceptionally high write performance</strong> (e.g., Logging, Real-time Metrics).</p>
</li>
<li><p><strong>Pros</strong>: Near-instant write response.</p>
</li>
</ul>
<hr />
<h2>Technical Implementation (Step-by-Step)</h2>
<p>Follow this roadmap to see how I build a production-ready demo using Clean Architecture:</p>
<h3>1. Project Initialization</h3>
<p>Bootstrap the project using the AI-Native CLI:</p>
<pre><code class="language-bash">npx nodejs-quickstart-structure@latest init
</code></pre>
<p><em>Selection Guide:</em></p>
<ul>
<li><p>Project name: <code>nodejs-service-caching-pattern</code></p>
</li>
<li><p>Architecture: <code>Clean Architecture</code></p>
</li>
<li><p>Database: <code>MySQL</code></p>
</li>
<li><p>Caching: <code>Redis</code></p>
</li>
<li><p>Communication: <code>REST APIs</code></p>
</li>
</ul>
<h3>2. Defining Domain Interfaces</h3>
<p>Abstract the caching and repository logic to ensure true decoupling.</p>
<ul>
<li><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/domain/services/ICacheService.ts">ICacheService.ts</a></li>
</ul>
<pre><code class="language-typescript">export interface ICacheService {
  get&lt;T&gt;(key: string): Promise&lt;T | null&gt;;
  set(key: string, value: unknown, ttl?: number): Promise&lt;void&gt;;
  del(key: string): Promise&lt;void&gt;;
  getOrSet&lt;T&gt;(key: string, fetcher: () =&gt; Promise&lt;T&gt;, ttl?: number): Promise&lt;T&gt;;
}
</code></pre>
<ul>
<li><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/domain/repositories/IUserRepository.ts">IUserRepository.ts</a></li>
</ul>
<h3>3. Infrastructure Layer</h3>
<p>Implementation for Redis and Sequelize (MySQL).</p>
<ul>
<li><p><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/infrastructure/caching/redisClient.ts">redisClient.ts</a></p>
</li>
<li><p><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/infrastructure/repositories/UserRepository.ts">UserRepository.ts</a></p>
</li>
</ul>
<h3>4. Database Seeding: Generate 1,000 dummy users for demo purposes.</h3>
<ul>
<li><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/flyway/sql/V20260319__seed_1000_users.sql">V20260319__seed_1000_users.sql</a></li>
</ul>
<h3>5. Implementing the Use Cases</h3>
<p>This is where the pattern logic lives.</p>
<ul>
<li><strong>Read-Through Example</strong>: <a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/usecases/getUserInfoReadThrough.ts">getUserInfoReadThrough.ts</a></li>
</ul>
<pre><code class="language-typescript">// The cache provider handles DB fetching upon miss
return await this.cacheService.getOrSet&lt;User | null&gt;(cacheKey, async () =&gt; {
    return await this.userRepository.findById(id);
}, 3600);
</code></pre>
<ul>
<li><strong>Write-Back Example</strong>: <a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/usecases/updateUserWriteBack.ts">updateUserWriteBack.ts</a></li>
</ul>
<pre><code class="language-typescript">// Update cache immediately, DB updates in background
await this.cacheService.set(cacheKey, updatedUser, 3600);
this.asyncDatabaseUpdate(updatedUser); 
</code></pre>
<p>You can check sample code at here:</p>
<ul>
<li><p><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/usecases/createUserWriteThrough.ts">createUserWriteThrough.ts</a></p>
</li>
<li><p><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/usecases/createUserWriteAround.ts">createUserWriteAround.ts</a></p>
</li>
<li><p><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/usecases/updateUserWriteBack.ts">updateUserWriteBack.ts</a></p>
</li>
</ul>
<h3>6. API &amp; Documentation</h3>
<ul>
<li><p><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/interfaces/controllers/cacheDemoController.ts">cacheDemoController.ts</a></p>
</li>
<li><p><a href="https://github.com/paudang/nodejs-service-caching-pattern/blob/main/src/config/swagger.yml">swagger.yml</a></p>
</li>
</ul>
<hr />
<h2>How to Test &amp; Verify</h2>
<p>Once deployed, you can trigger these endpoints to verify the internal logic:</p>
<h3>1. Test Cache-Aside / Read-Through (Read Path)</h3>
<ul>
<li><p><strong>First Call (Cold Cache)</strong>: <code>curl -X GET http://localhost:3000/api/demo/cache-aside/1</code></p>
<ul>
<li><em>Internal:</em> App checks Redis (Miss) -&gt; Queries MySQL -&gt; Updates Redis -&gt; Returns.</li>
</ul>
</li>
<li><p><strong>Subsequent Call (Warm Cache)</strong>: Repeat the command.</p>
<ul>
<li><em>Internal:</em> App checks Redis (Hit) -&gt; Returns immediately with zero DB overhead.</li>
</ul>
</li>
</ul>
<h3>2. Test Write-Through (Sync Write)</h3>
<ul>
<li><p><strong>Trigger</strong>: <code>curl -X POST http://localhost:3000/api/demo/write-through -H "Content-Type: application/json" -d '{"name": "Performance", "email": "perf@test.com"}'</code></p>
<ul>
<li><em>Internal:</em> Service writes to MySQL AND Redis simultaneously.</li>
</ul>
</li>
</ul>
<h3>3. Test Write-Around (Clean Write)</h3>
<ul>
<li><p><strong>Trigger</strong>: <code>curl -X POST http://localhost:3000/api/demo/write-around -H "Content-Type: application/json" -d '{"name": "Guest", "email": "guest@test.com"}'</code></p>
<ul>
<li><em>Internal:</em> Writes to MySQL, then calls <code>DEL</code> to invalidate the Redis key. The next read will be a Miss to load the fresh data.</li>
</ul>
</li>
</ul>
<h3>4. Test Write-Back (Async Write)</h3>
<ul>
<li><p><strong>Trigger</strong>: <code>curl -X PUT http://localhost:3000/api/demo/write-back/1 -H "Content-Type: application/json" -d '{"name": "Fast Update"}'</code></p>
<ul>
<li><em>Internal:</em> Updates Redis immediately (super fast response). The DB update happens after a short delay asynchronously.</li>
</ul>
</li>
</ul>
<hr />
<h2>Final Thoughts on AI-Native Tooling</h2>
<p>What makes <code>nodejs-quickstart-structure</code> special is not just the speed of initialization, but its <strong>AI-Native</strong> nature. With <code>.cursorrules</code> and pre-built prompts, it ensures that your project maintains Clean Architecture and consistent coding standards automatically from development to production.</p>
<p><strong>Full Source Code</strong>: <a href="https://github.com/paudang/nodejs-service-caching-pattern">GitHub Repository</a></p>
<hr />
<p><em>I hope this guide helps you choose the right caching pattern for your next project</em></p>
]]></content:encoded></item><item><title><![CDATA[Stop Reinventing the Wheel: How I Built the Ultimate CLI for Node.js Microservices]]></title><description><![CDATA[Let's be honest: setting up a new Node.js microservice is a chore. By the time you've configured TypeScript, connected MySQL, set up Redis for caching, and wired a Kafka producer, you've already spent]]></description><link>https://paudang.hashnode.dev/ultimate-nodejs-microservice-cli</link><guid isPermaLink="true">https://paudang.hashnode.dev/ultimate-nodejs-microservice-cli</guid><category><![CDATA[Node.js]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[Clean Architecture]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Fri, 20 Mar 2026 01:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/b282b6f2-9500-4599-99c1-ae0e4ccd9807.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's be honest: setting up a new Node.js microservice is a chore. By the time you've configured TypeScript, connected MySQL, set up Redis for caching, and wired a Kafka producer, you've already spent hours—and you haven't written a single line of business logic yet.</p>
<p>After years of building distributed systems, I decided to automate the "boring stuff." The result is <code>nodejs-quickstart-structure</code>, a CLI tool designed to take you from zero to a production-ready scaffold in under 60 seconds.</p>
<hr />
<h3>Why another boilerplate?</h3>
<p>Most starters in the Node.js ecosystem fall into two categories:</p>
<ol>
<li><p><strong>The "Hello World" starters:</strong> Too simple. Great for learning, useless for production.</p>
</li>
<li><p><strong>The "Everything-in-the-Box" monoliths:</strong> Too bloated. You spend more time deleting features you don't need than actually coding.</p>
</li>
</ol>
<p>I wanted something different: A <strong>Clean Architecture</strong> scaffold that is modular, testable, and comes with a "Production-Grade" infrastructure out of the box.</p>
<h3>The Technical Deep Dive</h3>
<h4>1. Clean Architecture: Separating Concerns</h4>
<p>We don't just throw everything into a <code>src</code> folder. The CLI generates a structure based on Uncle Bob's principles:</p>
<ul>
<li><p><strong>Domain Layer:</strong> Your business entities and logic (Zero dependencies).</p>
</li>
<li><p><strong>Use Cases:</strong> Orchestrating the flow of data.</p>
</li>
<li><p><strong>Infrastructure Layer:</strong> Where the "heavy lifting" happens (Sequelize, Kafka, Express).</p>
</li>
</ul>
<p>This separation means you can swap your database or web framework without ever touching your core business rules.</p>
<h4>2. Event-Driven by Default (Kafka Integration)</h4>
<p>In a modern microservice world, services need to talk. We’ve built-in a robust <strong>Kafka integration</strong>.</p>
<ul>
<li><p><strong>Pre-configured Producers/Consumers:</strong> No more struggling with <code>kafkajs</code> boilerplate.</p>
</li>
<li><p><strong>Reliability:</strong> It’s designed to handle connection retries and heartbeats properly.</p>
</li>
</ul>
<h4>3. Solving the "It Works on My Machine" Syndrome</h4>
<p>One of the most annoying bugs I encountered was the <strong>Case-Sensitive naming mismatch</strong> between Windows (Case-Insensitive) and Linux (Case-Sensitive).</p>
<p>In <code>nodejs-quickstart-structure</code>, I’ve integrated:</p>
<ul>
<li><p><strong>Strict ESLint Import Rules:</strong> Catches naming mismatches in your IDE.</p>
</li>
<li><p><strong>Full Docker Stack:</strong> A <code>docker-compose.yml</code> that stands up your App, MySQL, Kafka, and Redis in a unified Linux environment. If it runs on your local Docker, it will run on your Production Kubernetes.</p>
</li>
</ul>
<hr />
<h3>The Power of One Command</h3>
<p>You don't need to clone a repo. You don't need to manually edit config files. Just run:</p>
<pre><code class="language-bash">npx nodejs-quickstart-structure init
</code></pre>
<p>What you get instantly:</p>
<p>✅ Clean Architecture folder structure.</p>
<p>✅ Sequelize ORM with MySQL &amp; Flyway migrations.</p>
<p>✅ Redis integration for high-performance caching.</p>
<p>✅ Kafka setup for asynchronous event-driven messaging.</p>
<p>✅ Unit Testing environment with Jest.</p>
<p>✅ CI/CD workflows for GitHub Actions.</p>
<p>Final Thoughts &amp; Open Source Building this CLI was about more than just automation—it was about creating a standard. Whether you are a solo developer or part of a large team, having a consistent scaffold means anyone can jump into the codebase and understand it immediately.</p>
<p>I’m looking for feedback! Try it out, break it, and let me know how we can make it even better.</p>
<p>👉 GitHub: [<a href="https://github.com/paudang/nodejs-quickstart-structure">https://github.com/paudang/nodejs-quickstart-structure</a>]</p>
<p>👉 NPM: [<a href="https://www.npmjs.com/package/nodejs-quickstart-structure%5C%5D">https://www.npmjs.com/package/nodejs-quickstart-structure\]</a></p>
]]></content:encoded></item><item><title><![CDATA[Stop Generate Messy Code – Start with a Senior-Grade Node.js Structure]]></title><description><![CDATA[The "AI Hallucination" in Software Architecture
We’ve all been there. You prompt Cursor or Claude to "Set up a Node.js Clean Architecture," and it does a decent job—at first. But as soon as you need t]]></description><link>https://paudang.hashnode.dev/stop-generate-messy-code-start-with-a-senior-grade-node-js-structure</link><guid isPermaLink="true">https://paudang.hashnode.dev/stop-generate-messy-code-start-with-a-senior-grade-node-js-structure</guid><category><![CDATA[Node.js]]></category><category><![CDATA[architecture]]></category><category><![CDATA[backend]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Fri, 13 Mar 2026 15:41:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/0680ad92-1280-4b6f-b5a5-17dfbdfe1ac9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>The "AI Hallucination" in Software Architecture</h3>
<p>We’ve all been there. You prompt Cursor or Claude to "Set up a Node.js Clean Architecture," and it does a decent job—at first. But as soon as you need to integrate <strong>Redis</strong> for caching, <strong>Kafka</strong> for event-driven messaging, and <strong>Docker</strong> for deployment, the "AI-generated" structure starts to crumble. It lacks cohesion, ignores edge cases, and isn't "Production-Ready."</p>
<h3>The Solution: A Framework-Agnostic "Golden Standard"</h3>
<p>I spent hundreds of hours refining the <code>nodejs-quickstart-structure</code>. My goal wasn't just to create another boilerplate, but to build a <strong>Professional Toolkit</strong>—the kind of structure a Tech Lead takes from company to company to skip two weeks of setup and get straight to business logic.</p>
<p>Today, it has reached nearly <strong>3,000 downloads</strong> and holds the <strong>#1 spot on NPM search</strong> for Node.js quickstart structures.</p>
<h3>What’s Inside the "Growth" Phase?</h3>
<p>The tool currently supports:</p>
<ul>
<li><p><strong>Clean Architecture:</strong> Strict separation of concerns.</p>
</li>
<li><p><strong>Hybrid Communication:</strong> Support for REST and GraphQL.</p>
</li>
<li><p><strong>Performance:</strong> Built-in Redis caching logic.</p>
</li>
<li><p><strong>DevX:</strong> Optimized <code>.cursorrules</code> so your AI assistant actually understands your code patterns.</p>
</li>
</ul>
<h3>Sneak Peek: The v1.16.0 Kafka Update (Coming Next Week)</h3>
<p>I’m currently finalizing a major update focused on <strong>Event-Driven Architecture</strong>:</p>
<ul>
<li><p><strong>BaseConsumer Abstraction:</strong> Automated JSON parsing, schema validation (Zod), and robust error handling.</p>
</li>
<li><p><strong>The "Golden Flow" Demo:</strong> A real-world integration showing <code>API Request -&gt; DB Save -&gt; Cache Invalidation -&gt; Kafka Event</code>.</p>
</li>
<li><p><strong>AI-Native Kafka:</strong> Updated AI rules to help you generate new consumers/producers that follow the established architectural pattern.</p>
</li>
</ul>
<p><strong>Join the Journey</strong> If you’re tired of "re-inventing the wheel" for every new microservice, give this structure a try.</p>
<p>👉 <strong>NPM:</strong> <code>nodejs-quickstart-structure</code></p>
<p>👉 <strong>GitHub:</strong> <a href="https://github.com/paudang/nodejs-quickstart-structure">paudang/nodejs-quickstart-structure: A CLI to scaffold Node.js microservices with MVC or Clean Architecture</a></p>
<p>I’m on a mission to hit 10k downloads by the end of the year. If this tool saves you even an hour of work, I’d be honored to have your 🌟 on GitHub!</p>
]]></content:encoded></item><item><title><![CDATA[15-Minute Node.js Setup: From Zero to Production (GraphQL, PostgreSQL, Docker & CI/CD)]]></title><description><![CDATA[Hey DEV community! 👋
Today we're upgrading our skills with a modern, battle-tested stack for large applications: Node.js + GraphQL + PostgreSQL (managed via Flyway) + Docker + GitHub Actions.
If you']]></description><link>https://paudang.hashnode.dev/15-minute-node-js-setup-from-zero-to-production-graphql-postgresql-docker-ci-cd</link><guid isPermaLink="true">https://paudang.hashnode.dev/15-minute-node-js-setup-from-zero-to-production-graphql-postgresql-docker-ci-cd</guid><category><![CDATA[Node.js]]></category><category><![CDATA[full stack]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[backend]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Mon, 02 Mar 2026 02:08:15 GMT</pubDate><content:encoded><![CDATA[<p>Hey DEV community! 👋</p>
<p>Today we're upgrading our skills with a modern, battle-tested stack for large applications: <strong>Node.js + GraphQL + PostgreSQL (managed via Flyway) + Docker + GitHub Actions</strong>.</p>
<p>If you're tired of creating dozens of REST endpoints for a single complex UI screen, or struggling with over-fetching slowing down your mobile apps, GraphQL is your ultimate savior. This step-by-step guide is designed so even a Junior Developer can set everything up from scratch.</p>
<p>🎯 <strong>Source Code</strong>: I've prepared a highly standardized boilerplate repo so you can clone it and follow along with the code. 🔗 <a href="https://github.com/paudang/nodejs-graphql-service">Reference Repo: nodejs-graphql-service</a> (The complete backend code is generated using this tool).</p>
<hr />
<h2>1. RESTful API vs GraphQL: Understanding the Core</h2>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ncmfa2ci2xdqcm7otxj0.png" alt="Image description" style="display:block;margin:0 auto" />

<p>Before typing any code, let's understand why we're choosing GraphQL.</p>
<h3>The RESTful API Perspective</h3>
<ul>
<li><p><strong>Mechanism:</strong> Based on Resources. You access multiple URLs for different resources (<code>GET /users</code>, <code>GET /posts/1</code>).</p>
</li>
<li><p><strong>Pros:</strong></p>
<ul>
<li><p>Easy to understand and strictly patterned.</p>
</li>
<li><p>Leverages HTTP-level caching (CDN, Browser cache, Varnish) perfectly.</p>
</li>
<li><p>Straightforward file uploads via <code>multipart/form-data</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Cons:</strong> The response data structure is <strong>inflexible</strong>. The backend returns a fixed set of fields, leading to Over-fetching (getting more data than you need) or Under-fetching (having to make additional API calls).</p>
</li>
</ul>
<h3>The GraphQL Perspective</h3>
<ul>
<li><p><strong>Mechanism:</strong> Only <strong>ONE Endpoint</strong> (usually <code>POST /graphql</code>). The frontend sends a specific query detailing exactly what fields it needs, and the backend returns precisely that shape.</p>
</li>
<li><p><strong>Pros:</strong></p>
<ul>
<li><p><strong>Smart Payload:</strong> Get exactly what you need—not a byte more.</p>
</li>
<li><p>Combine multiple resource types (User, Post, Comment) in a single network request (highly optimized for mobile).</p>
</li>
<li><p>Schema (Type Definitions) acts as living documentation. Front-end devs can code UI without waiting for the back-end implementation.</p>
</li>
</ul>
</li>
<li><p><strong>Cons:</strong></p>
<ul>
<li><p>Harder to cache at the HTTP layer (since queries are <code>POST</code> requests).</p>
</li>
<li><p>Prone to N+1 query problems on the backend if not carefully using DataLoader.</p>
</li>
<li><p>File uploads are trickier out of the box compared to REST.</p>
</li>
</ul>
</li>
</ul>
<hr />
<h2>2. Practical Application: When to use what?</h2>
<p>There is no silver bullet in programming. Choose the right tool for the job:</p>
<ul>
<li><p><strong>Stick with RESTful when:</strong></p>
<ul>
<li><p>Working on small projects with simple CRUD operations.</p>
</li>
<li><p>Building Public APIs for 3rd parties (Webhooks, payment gateways).</p>
</li>
<li><p>You need to heavily leverage HTTP caching mechanisms.</p>
</li>
</ul>
</li>
<li><p><strong>Switch to GraphQL when:</strong></p>
<ul>
<li><p>The system has complex UIs or Dashboards pulling data from multiple tables/services.</p>
</li>
<li><p>Developing Mobile Apps where bandwidth and payload optimization is crucial.</p>
</li>
<li><p>Front-end and Back-end teams work independently (Front-end can request what they want via Schema).</p>
</li>
</ul>
</li>
</ul>
<hr />
<h2>3. Setup Source Code From Zero (Production Standard)</h2>
<p>We will set up an <code>apollo-server-express</code> GraphQL server connecting to PostgreSQL via <code>sequelize</code> (Database config will be handled in the Docker section).</p>
<h3>Step 3.1: Initialize &amp; Install Dependencies</h3>
<p>Create project folder:</p>
<pre><code class="language-bash">mkdir nodejs-graphql-service
cd nodejs-graphql-service
npm init -y
</code></pre>
<p>Install Core libraries (Express, Apollo Server, Security, PostgreSQL):</p>
<pre><code class="language-bash">npm install express @apollo/server graphql cors helmet hpp express-rate-limit dotenv morgan sequelize pg pg-hstore
</code></pre>
<p>Install Dev dependencies (TypeScript):</p>
<pre><code class="language-bash">npm install -D typescript @types/node @types/express @types/cors @types/morgan ts-node tsconfig-paths
</code></pre>
<p>Open <a href="https://github.com/paudang/nodejs-graphql-service/blob/main/package.json">package.json</a> and add these basic scripts for dev and CI/CD building:</p>
<pre><code class="language-json">"scripts": {
  "dev": "ts-node -r tsconfig-paths/register src/index.ts",
  "build": "tsc",
  "test": "echo \"Error: no test specified\" &amp;&amp; exit 0"
}
</code></pre>
<h3>Step 3.2: PostgreSQL Connection &amp; Model Setup (Sequelize)</h3>
<p>Since real data lives in a database, let's configure <a href="https://github.com/paudang/nodejs-graphql-service/blob/main/src/config/database.ts">src/config/database.ts</a>:</p>
<pre><code class="language-typescript">import { Sequelize } from 'sequelize';
import dotenv from 'dotenv';

dotenv.config();

const sequelize = new Sequelize(
  process.env.DB_NAME || 'demo',
  process.env.DB_USER || 'postgres',
  process.env.DB_PASSWORD || 'root',
  {
    host: process.env.DB_HOST || '127.0.0.1',
    dialect: 'postgres',
    logging: false,
    port: parseInt(process.env.DB_PORT || '5432')
  }
);

export default sequelize;
</code></pre>
<p>Along with that, create a Model representing the Users table at <code>src/models/User.ts</code>:</p>
<pre><code class="language-typescript">import { DataTypes, Model, Optional } from 'sequelize';
import sequelize from '../config/database';

interface UserAttributes { id: number; name: string; email: string; }
interface UserCreationAttributes extends Optional&lt;UserAttributes, 'id'&gt; {}

class User extends Model&lt;UserAttributes, UserCreationAttributes&gt; implements UserAttributes {
  public id!: number;
  public name!: string;
  public email!: string;
}

User.init({
  id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true },
  name: { type: DataTypes.STRING, allowNull: false },
  email: { type: DataTypes.STRING, allowNull: false, unique: true }
}, { sequelize, tableName: 'users', timestamps: false });

export default User;
</code></pre>
<h3>Step 3.3: GraphQL TypeDefs &amp; Resolvers</h3>
<p>Create <code>src/graphql/typeDefs.ts</code>:</p>
<pre><code class="language-typescript">export const typeDefs = `#graphql
  type User {
    id: ID!
    name: String!
    email: String!
  }

  type Query {
    getAllUsers: [User]
  }

  type Mutation {
    createUser(name: String!, email: String!): User
  }
`;
</code></pre>
<p>Create <code>src/graphql/resolvers.ts</code>. Notice that we query the Sequelize Model directly instead of using mock data:</p>
<pre><code class="language-typescript">import { GraphQLError } from 'graphql';
import User from '../models/User'; 

export const resolvers = {
  Query: {
    getAllUsers: async () =&gt; {
      try {
        return await User.findAll(); // Dive straight into PostgreSQL
      } catch (error: any) {
        throw new GraphQLError(error.message, { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
      }
    }
  },
  Mutation: {
    createUser: async (_: any, { name, email }: { name: string, email: string }) =&gt; {
      try {
        return await User.create({ name, email }); // INSERT new row
      } catch (error: any) {
        throw new GraphQLError(error.message, { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
      }
    }
  }
};
</code></pre>
<h3>Step 3.4: Entry Point (src/index.ts)</h3>
<p>A major challenge when working with Apollo Server is a blank screen accessing the Apollo Sandbox due to Content-Security-Policy (CSP) restrictions from <code>helmet</code>. Here is the complete fix:</p>
<pre><code class="language-typescript">import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import dotenv from 'dotenv';
import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
import { typeDefs } from './graphql/typeDefs';
import { resolvers } from './graphql/resolvers';
import sequelize from './config/database';

dotenv.config();
const app = express();
const port = process.env.PORT || 3000;

// Fix blank screen for Apollo Sandbox with custom CSP
app.use(helmet({
  crossOriginEmbedderPolicy: false,
  contentSecurityPolicy: {
    directives: {
      imgSrc: [`'self'`, 'data:', 'apollo-server-landing-page.cdn.apollographql.com'],
      scriptSrc: [`'self'`, `https: 'unsafe-inline'`],
      manifestSrc: [`'self'`, 'apollo-server-landing-page.cdn.apollographql.com'],
      frameSrc: [`'self'`, 'sandbox.embed.apollographql.com'],
    },
  },
}));

app.use(cors());
app.use(express.json());

const startServer = async () =&gt; {
    const server = new ApolloServer({
      typeDefs,
      resolvers,
      plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })], 
    });

    await server.start();
    app.use('/graphql', expressMiddleware(server));

    // Wait for DB connection before exposing port
    await sequelize.sync(); 
    app.listen(port, () =&gt; {
        console.log(`🚀 GraphQL Server running at http://localhost:${port}/graphql`);
    });
};

startServer();
</code></pre>
<hr />
<h2>4. Database Configuration (Docker, PostgreSQL &amp; Flyway)</h2>
<p>We shouldn't run a barebones database locally. In production, your database schema evolves constantly. Thus, managing schema migrations using a tool like <strong>Flyway</strong> is mandatory. We will use <a href="https://github.com/paudang/nodejs-graphql-service/blob/main/docker-compose.yml">docker-compose.yml</a> to spin up our Node App, PostgreSQL, and Flyway containers seamlessly.</p>
<p>Create <a href="https://github.com/paudang/nodejs-graphql-service/blob/main/docker-compose.yml">docker-compose.yml</a> at the root folder:</p>
<pre><code class="language-yaml">services:
  app:
    build: .
    ports:
      - "${PORT:-3000}:3000"
    depends_on:
      - db
      - flyway
    environment:
      - PORT=3000
      - DB_HOST=db
      - DB_USER=postgres
      - DB_PASSWORD=root
      - DB_NAME=demo

  db:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: root
      POSTGRES_DB: demo
    ports:
      - "${DB_PORT:-5432}:5432"
    volumes:
      - ./flyway/sql:/docker-entrypoint-initdb.d

  flyway:
    image: flyway/flyway
    command: -connectRetries=60 migrate
    volumes:
      - ./flyway/sql:/flyway/sql
    environment:
      FLYWAY_URL: jdbc:postgresql://db:5432/demo
      FLYWAY_USER: postgres
      FLYWAY_PASSWORD: root
    depends_on:
      - db
</code></pre>
<p><strong>Why is this powerful?</strong> When you run <code>docker-compose up -d</code>, the <code>flyway</code> container waits for <code>db</code> (Postgres) to be ready. It then automatically reads <code>.sql</code> files in <code>./flyway/sql</code> and applies them (Migrations) before anything else.</p>
<p>To give Flyway a migration to run, create <code>flyway/sql/V1__Create_users_table.sql</code>:</p>
<pre><code class="language-sql">CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  email VARCHAR(255) UNIQUE NOT NULL
);
</code></pre>
<p>Only after all dependencies are ready will the Node.js <code>app</code> connect. This is exceptionally safe for production.</p>
<hr />
<h2>5. CI/CD Automation with GitHub Actions</h2>
<p>Code working locally is no guarantee it won't crash on the server due to dependency flaws. To automate code quality checks and tests on every <code>git push</code>, let's inject a CI/CD workflow.</p>
<p>Create the <code>.github/workflows/</code> folder and drop this <a href="https://github.com/paudang/nodejs-graphql-service/blob/main/.github/workflows/ci.yml">ci.yml</a> file into it:</p>
<pre><code class="language-yaml">name: Node.js CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [18.x, 20.x] # Run tests on multiple Node versions

    steps:
    - uses: actions/checkout@v3
    
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        cache: 'npm'
        
    - name: Install Dependencies
      run: npm ci # Use npm ci for reliable builds
      
    - name: Lint Code
      run: npm run lint
      
    - name: Run Tests
      run: npm test # Keep those tests green!
      
    - name: Build Source
      run: npm run build --if-present
</code></pre>
<hr />
<h2>6. Apollo Sandbox Live Demo</h2>
<p>Everything is perfectly set up. Run <code>docker-compose up -d</code> and <code>npm run dev</code>. Open your browser to <code>http://localhost:3000/graphql</code>. You'll seamlessly land on the <strong>Apollo Sandbox</strong> interface thanks to our prior Helmet CSP configuration.</p>
<p>Try running these snippets in the Query window:</p>
<p><strong>Add a new User to PostgreSQL:</strong></p>
<pre><code class="language-graphql">mutation CreateUser {
  createUser(name: "DEV Expert", email: "author@dev.to") {
    id
    name
    email
  }
}
</code></pre>
<p><strong>Fetch 100% real user data:</strong></p>
<pre><code class="language-graphql">query GetAllUsers {
  getAllUsers {
    id
    name
    email
  }
}
</code></pre>
<img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qmo0ia6gpej2y62opy8h.png" alt="Image description" style="display:block;margin:0 auto" />

<p>The data is fetched directly from Postgres and returned cleanly. If the frontend requests 3 fields (id, name, email), the backend gives exactly 3 fields. No bloated timestamps or unused columns!</p>
<hr />
<h2>7. The Ultimate Shortcut... 🤫</h2>
<p>Reading through this detailed guide, you might feel a bit overwhelmed. Setting up package.json, configuring Apollo, fixing security policies, tweaking Docker-compose with Flyway, and writing GitHub Actions manually can drain an entire weekend.</p>
<p><strong>How to never do this manual setup again:</strong></p>
<p>From our painful experiences bootstrapping projects, my team developed a CLI Engine that generates an entire <strong>GraphQL Source Code (Clean Architecture/MVC) AUTOMATICALLY IN EXACTLY 10 SECONDS.</strong></p>
<p>The tool is called: <code>nodejs-quickstart-structure</code></p>
<p>In your terminal, simply run:</p>
<pre><code class="language-bash">npx nodejs-quickstart-structure init
</code></pre>
<ul>
<li><p>Select <code>TypeScript</code></p>
</li>
<li><p>Select <code>Clean Architecture</code></p>
</li>
<li><p>Select <code>PostgreSQL</code> Database</p>
</li>
<li><p>Select <code>GraphQL</code> Communication</p>
</li>
<li><p>Select <code>GitHub Actions</code> CI/CD</p>
</li>
</ul>
<p><strong>BOOM! 💥</strong> You instantly get a production-ready boilerplate identical to what we've just built together, fully layered with Controllers, Repositories, and Entities. Just configure the port and start coding your business logic without typing a single boilerplate character.</p>
<p>🔗 <strong>Check out the CLI tool here:</strong> <a href="https://github.com/paudang/nodejs-quickstart-structure">github.com/paudang/nodejs-quickstart-structure</a></p>
<p>Don't forget to drop a Star (⭐) on the repo if this tool saves your deadlines!</p>
]]></content:encoded></item><item><title><![CDATA[Build Production-Ready Node.js Microservices in 60 Seconds: MVC vs Clean Architecture]]></title><description><![CDATA[Hi everyone!
As Node.js developers, we've all been there. You have a great idea for a new project, but before you can write a single line of business logic, you have to spend hours setting up the foun]]></description><link>https://paudang.hashnode.dev/build-production-ready-node-js-microservices-in-60-seconds-mvc-vs-clean-architecture</link><guid isPermaLink="true">https://paudang.hashnode.dev/build-production-ready-node-js-microservices-in-60-seconds-mvc-vs-clean-architecture</guid><category><![CDATA[Node.js]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[software architecture]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[backend]]></category><category><![CDATA[Docker]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Pau Dang]]></dc:creator><pubDate>Thu, 26 Feb 2026 12:50:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/a33b67a1-0b1e-4afb-aaae-5ee7035b0906.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hi everyone!</p>
<p>As Node.js developers, we've all been there. You have a great idea for a new project, but before you can write a single line of business logic, you have to spend hours setting up the foundation.</p>
<p>You know the drill:</p>
<ol>
<li><p>Copy-paste a folder structure from an old project.</p>
</li>
<li><p>Configure <code>ESLint</code>, <code>Prettier</code>, and <code>TypeScript</code>.</p>
</li>
<li><p>Set up Docker and <code>docker-compose</code>.</p>
</li>
<li><p>Wire up the database connection.</p>
</li>
<li><p>Build the base Controller/Service layers.</p>
</li>
</ol>
<p>It’s not hard, but it’s tedious. It’s called <strong>"Boilerplate Fatigue,"</strong> and it kills your momentum. What if there was a way to just skip straight to the fun part of coding?</p>
<p>To solve this, I built an interactive CLI tool called <code>nodejs-quickstart-structure</code>.</p>
<p>The goal is simple: <strong>Run one command, and get a professional, industry-standard Node.js project ready for production code.</strong> Best of all? You are in full control of the architecture you want.</p>
<p>Before we dive into the tool, let's talk about the biggest decision you have to make when structuring your new Node.js app: <strong>MVC vs Clean Architecture</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/979dc442-48b8-4fd4-97df-17919c64645b.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>🏛️ The Great Debate: MVC vs Clean Architecture</h2>
<p>Choosing the right folder structure is critical for your application's success.</p>
<h3>📌 What is MVC? (Model–View–Controller)</h3>
<p><strong>MVC</strong> is the classic software architecture pattern that divides an application into three interconnected parts:</p>
<ul>
<li><p><strong>Model</strong>: Manages data, database connections, and core business logic.</p>
</li>
<li><p><strong>View</strong>: Handles the user interface and presentation.</p>
</li>
<li><p><strong>Controller</strong>: Acts as the middleman, processing incoming requests, fetching data from the model, and pushing it to the view.</p>
</li>
</ul>
<p>👉 <strong>Best For</strong>: MVC is simple, fast to implement, and intuitively organized. It's ideal for small to medium projects, quick prototypes, and REST APIs where getting to market quickly is the priority.</p>
<h3>📌 What is Clean Architecture?</h3>
<p><strong>Clean Architecture</strong> (popularized by Robert C. Martin - Uncle Bob) emphasizes separating the business rules from the infrastructure. It is often represented as concentric circles with strict dependency rules pointing inward:</p>
<ul>
<li><p><strong>Entities</strong>: Core business objects and properties.</p>
</li>
<li><p><strong>Use Cases</strong>: Application-specific business rules.</p>
</li>
<li><p><strong>Interface Adapters</strong>: Bridges between use cases and external systems (Controllers, Presenters).</p>
</li>
<li><p><strong>Frameworks &amp; Drivers</strong>: Databases, Web Frameworks, UI, and external tools.</p>
</li>
</ul>
<p>👉 <strong>Best For</strong>: Clean Architecture is designed for maximum scalability, high testability, and long-term maintainability. It’s perfect for large enterprise projects, microservices, or complex systems expected to evolve heavily over time.</p>
<hr />
<h2>🚀 Introducing <code>nodejs-quickstart-structure</code></h2>
<p>There are plenty of generators out there, but they are either too simple (just a basic Express <code>app.js</code>) or too opinionated (forcing a specific framework you don't like).</p>
<p><code>nodejs-quickstart-structure</code> is designed to balance <strong>speed</strong> with <strong>professional standards</strong>, letting you pick exactly how you want your app scaffolded.</p>
<img src="https://cdn.hashnode.com/uploads/covers/69a02d205fd4d31c613f5cd8/22dfb35f-addf-4be9-b631-d6149e10b1c3.gif" alt="" style="display:block;margin:0 auto" />

<h3>✨ Key Features:</h3>
<ul>
<li><p><strong>Architecture Agnostic</strong>: Choose between <strong>MVC</strong> for speed or <strong>Clean Architecture</strong> for strict separation of concerns.</p>
</li>
<li><p><strong>Language Support</strong>: First-class support for both <strong>JavaScript</strong> and <strong>TypeScript</strong>.</p>
</li>
<li><p><strong>Database Ready</strong>: Auto-configured connections for <strong>MongoDB</strong>, <strong>MySQL</strong>, or <strong>PostgreSQL</strong> using Mongoose/Sequelize.</p>
</li>
<li><p><strong>Microservices &amp; Event-Driven</strong>: Optional <strong>Kafka</strong> integration for robust message brokering.</p>
</li>
<li><p><strong>Performance Caching</strong>: Built-in <strong>Redis</strong> or <strong>Memory cache</strong> support.</p>
</li>
<li><p><strong>DevOps Friendly</strong>:</p>
<ul>
<li><p>Generates a complete <code>docker-compose.yml</code> instantly wiring up your DB, Redis, Kafka, and Zookeeper.</p>
</li>
<li><p>Optimized <strong>Multi-Stage Dockerfile</strong> for small, secure production images.</p>
</li>
<li><p>CI/CD templates automatically included for <strong>GitHub Actions</strong>, <strong>Jenkins</strong>, or <strong>GitLab</strong>.</p>
</li>
</ul>
</li>
<li><p><strong>Code Quality</strong>: Pre-configured with <code>ESLint</code> (Flat config), <code>Prettier</code>, <code>Husky</code>, and <code>Lint-staged</code>.</p>
</li>
<li><p><strong>Logging</strong>: Professional <code>Winston</code> + <code>Morgan</code> setup out of the box.</p>
</li>
<li><p><strong>Deployment</strong>: Ship confidently with an integrated <strong>PM2</strong> Ecosystem Configuration for zero-downtime reloads and robust process management.</p>
</li>
</ul>
<hr />
<h2>💻 Installation &amp; Usage</h2>
<p>It's published on npm. Start by installing the CLI globally:</p>
<pre><code class="language-bash">npm install -g nodejs-quickstart-structure
</code></pre>
<h3>Let's Scaffold a Project!</h3>
<p>Navigate to your empty workspace and simply run:</p>
<pre><code class="language-bash">nodejs-quickstart init
</code></pre>
<h2>Quick Start (Recommended)</h2>
<p>You can run the generator directly without installing it globally:</p>
<pre><code class="language-bash">npx nodejs-quickstart-structure init
</code></pre>
<p>The CLI will fire up and ask you a few interactive questions:</p>
<ol>
<li><p><strong>Project Name</strong>: <code>my-awesome-app</code></p>
</li>
<li><p><strong>Language</strong>: <code>TypeScript</code> / <code>JavaScript</code></p>
</li>
<li><p><strong>Architecture</strong>: <code>Clean Architecture</code> / <code>MVC</code></p>
</li>
<li><p><strong>Database</strong>: <code>PostgreSQL</code> / <code>MySQL</code> / <code>MongoDB</code></p>
</li>
<li><p><strong>Caching</strong>: <code>Redis</code> / <code>Memory cache</code></p>
</li>
<li><p><strong>Communication</strong>: <code>REST APIs</code> / <code>Kafka</code></p>
</li>
<li><p><strong>CI/CD</strong>: <code>GitHub Actions</code> / <code>Jenkins</code> / <code>GitLab</code></p>
</li>
</ol>
<p>And... <strong>BOOM!</strong> 💥</p>
<p>Within seconds, you have a fully scaffolded, Dockerized project structure ready to run:</p>
<pre><code class="language-text">my-awesome-app/
├── src/
│   ├── config/           # Environment variables, db config, swagger
│   ├── controllers/      # (MVC) or interfaces/controllers (Clean Arch)
│   ├── routes/           # (MVC) or interfaces/routes (Clean Arch)
│   ├── usecases/         # (Clean Arch) Application Business Rules
│   ├── domain/           # (Clean Arch) Enterprise Business Rules
│   ├── infrastructure/   # (Clean Arch) Database repositories, external services
│   └── index.ts          # Express Entry point
├── docker-compose.yml    # Fully configured services matrix
├── Dockerfile            # Multi-stage production image
├── .eslintrc.mjs         # Flat config
├── package.json
└── ...
</code></pre>
<hr />
<h2>🛠️ Massive Customizability</h2>
<p>The tool supports over <strong>160 different core configuration combinations</strong>, rigorously tested on Windows and Linux via automated E2E pipelines.</p>
<p>If you choose <strong>TypeScript + Clean Architecture + PostgreSQL + Kafka + Redis</strong>, the tool will:</p>
<ol>
<li><p>Generate the standard inward-facing Clean Architecture folder structure.</p>
</li>
<li><p>Install the <code>pg</code> and <code>sequelize</code> drivers, creating dynamic DB configurations.</p>
</li>
<li><p>Set up the <code>kafkajs</code> client and broker configs.</p>
</li>
<li><p>Auto-wire the <code>ioredis</code> cache client.</p>
</li>
<li><p>Create fully dockerized containers for Postgres, Redis, Kafka, and Zookeeper so everything boots with <code>docker-compose up</code>.</p>
</li>
<li><p>Generate beautiful <code>Swagger</code> (OpenAPI) docs.</p>
</li>
</ol>
<p>You get to skip days of painful environment debugging and jump straight to writing the code that actually matters to your product.</p>
<h2>🚀 Roadmap &amp; Upcoming Features</h2>
<p>We are constantly working to improve <code>nodejs-quickstart-structure</code> and make it the most robust boilerplate generator for Node.js.</p>
<p>👉Documents: <a href="https://paudang.github.io/nodejs-quickstart-structure">[Nodejs Quickstart Structure]</a></p>
<p>You can track our current progress, see what features are being worked on, and vote for your favorites on our public Trello board:</p>
<p>👉 <a href="https://trello.com/b/TPTo8ylF/nodejs-quickstart-structure-product"><strong>View our Public Roadmap on Trello</strong></a></p>
<hr />
<h2>🤝 Open Source Contribution</h2>
<p>This project is entirely <strong>Open Source</strong> (ISC License). I’d love for you to try it out, break it, report bugs, or even contribute new features!</p>
<ul>
<li><p>⭐️ <strong>Star the GitHub Repo</strong>: <a href="https://github.com/paudang/nodejs-quickstart-structure">https://github.com/paudang/nodejs-quickstart-structure</a></p>
</li>
<li><p>📦 <strong>Check it out on NPM</strong>: <a href="https://www.npmjs.com/package/nodejs-quickstart-structure">https://www.npmjs.com/package/nodejs-quickstart-structure</a></p>
</li>
</ul>
<p>If you find this tool helpful in saving your precious boilerplate time, giving it a star on GitHub goes a long way in supporting its development. Let me know what you think in the comments below</p>
]]></content:encoded></item></channel></rss>