<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged nest</title>
<link>https://coderlegion.com/tag/nest</link>
<description>Powered by Question2Answer</description>
<item>
<title>Thinking auth in producation systems a dive on the backend</title>
<link>https://coderlegion.com/11214/thinking-auth-in-producation-systems-a-dive-on-the-backend</link>
<description>&lt;p&gt;When building an application, authentication is unavoidable. You can outsource it to services like Clerk or Better Auth and be productive fast, but that convenience often comes with trade-offs: third-party lock-in, limited control over flows, and opaque behavior when things go wrong.&lt;/p&gt;
&lt;p&gt;In production systems, authentication is not just about logging users in. It shapes your security model, influences your database design, and quietly dictates how scalable and debuggable your system will be.&lt;/p&gt;
&lt;p&gt;In this article, I’ll walk through how I designed and implemented authentication for a real production project, the decisions I had to make, and the compromises that came with them. Since all systems have different auth requirements, it might vary from your version.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Requirements for my project&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For this project, authentication needs to be intentionally simple:&lt;br&gt;
email + password–based registration and login, with Google OAuth as an alternative for both signup and sign-in.&lt;/p&gt;
&lt;p&gt;If a user registers using email and password, the email must be verified via a verification link. Once the email is verified, the user is automatically logged in. The frontend receives the required tokens and user context without forcing an additional login step.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Strategy&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For this project, I’m using a JWT-based authentication approach with short-lived access tokens and refresh tokens, with refresh token rotation enabled.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;private async generateTokens(
    userId: string,
    email: string,
    role: number,
    deviceId: string,
  ) {
    const accessTokenSecret =
      this.configService.get&amp;lt;string&amp;gt;('JWT_ACCESS_SECRET');

    const refreshTokenSecret = this.configService.get&amp;lt;string&amp;gt;(
      'JWT_REFRESH_TOKEN_SECRET',
    );

    const accessTokenExpiryRaw = this.configService.get&amp;lt;string&amp;gt;(
      'JWT_ACCESS_TOKEN_EXPIRE_TIME',
      '1h',
    );
    const refreshTokenExpiryRaw = this.configService.get&amp;lt;string&amp;gt;(
      'JWT_REFRESH_TOKEN_EXPIRE_TIME',
      '7d',
    );

    const accessTokenTtlMs = ms(accessTokenExpiryRaw);
    const refreshTokenTtlMs = ms(refreshTokenExpiryRaw);

    const [accessToken, refreshToken] = await Promise.all([
      this.jwtService.signAsync(
        { sub: userId, email, role },
        {
          secret: accessTokenSecret,
          expiresIn: Math.ceil(accessTokenTtlMs / 1000),
        },
      ),
      this.jwtService.signAsync(
        { sub: userId, email, role },
        {
          secret: refreshTokenSecret,
          expiresIn: Math.ceil(refreshTokenTtlMs / 1000),
        },
      ),
    ]);

    // Extract the signature part of the JWT
    const accessTokenSignature = accessToken.split('.')[2];

    // Keyv expects TTL in ms - cache key includes deviceId for device-specific validation
    await this.cacheManager.set(
      `${CacheKey.ACCESS_KEY}:${userId}:${deviceId}`,
      { tokenSignature: accessTokenSignature, deviceId },
      accessTokenTtlMs,
    );

    return { accessToken, refreshToken };
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To minimize authentication lookup latency, access tokens are cached in Redis, mapped to the corresponding user_id and device_id. This allows the system to validate active sessions without hitting the primary database on every authenticated request.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Device Identification&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Each client device is assigned a unique deviceId, generated on the backend.&lt;/p&gt;
&lt;p&gt;My first approach was to derive this identifier from the IP address and user agent. From a security perspective, this worked well. Tokens were tightly bound to their original context, and replaying them from elsewhere was difficult.&lt;/p&gt;
&lt;p&gt;In practice, though, IP addresses change far more often than you’d expect, especially for mobile users. The result was unnecessary session invalidation and a poor user experience.&lt;/p&gt;
&lt;p&gt;After weighing those trade-offs, I switched to deriving the deviceId from the user ID and user agent instead.&lt;/p&gt;
&lt;p&gt;The goal of the deviceId is simple:&lt;/p&gt;
&lt;p&gt;Avoid duplicate session entries in Redis when a user logs in multiple times from the same device&lt;br&gt;
Make session tracking and revocation possible on a per-device basis&lt;br&gt;
Add an extra check during token validation beyond signature and expiry&lt;br&gt;
By anchoring sessions to a deterministic deviceIdRedis maintains a single active access-token entry per device rather than accumulating redundant session data.&lt;/p&gt;
&lt;p&gt;In practice, access and refresh tokens are validated not just by their cryptographic signature and expiration, but also by the reason the deviceId they were issued for. This means that even if a token is leaked, it can’t be trivially replayed from a completely different device context unless the attacker also replicates the same user agent.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  private generateDeviceFingerprint(userId: string, userAgent: string): string {
    const raw = `${userId}|${userAgent}`;
    return crypto
      .createHash('sha256')
      .update(raw)
      .digest('hex')
      .substring(0, 32);
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;User agents aren’t secret, and this is not meant to be a perfect defense. What it does provide is a meaningful reduction in the blast radius of token leakage and protection against a large class of naive replay attacks.&lt;/p&gt;
&lt;p&gt;This approach intentionally trades stronger environmental binding for stability and usability. For this system, that trade-off is acceptable. The deviceId isn’t a cryptographic fingerprint; it’s a pragmatic mechanism to keep sessions predictable, revocable, and reasonably safe in production.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Schema design&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For authentication, the core requirements can be met with just two tables: one to represent the user, and another to track login sessions via refresh tokens.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Table users {
  id        uuid PK        // uuidv7
  name      string
  email     string UNIQUE NOT NULL
  password  string null // hashed password
  role      int NOT NULL   // 0 = user, 1 = admin, 2 = super_admin
  created_at timestamp
  updated_at timestamp
}
Table user_login_tokens {
  id                     uuid PK
  user_id                uuid FK -&amp;gt; users.id
  device_id              string
  refresh_token_signature string NOT NULL
  user_agent             string
  ip_address             string
  expires_at             timestamp NOT NULL
  revoked_at             timestamp
  created_at             timestamp
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Rate Limiting &amp;amp; Abuse Protection&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Authentication endpoints are a natural target for abuse, so basic rate limiting is enforced at the infrastructure level using Redis.&lt;/p&gt;
&lt;p&gt;Rather than applying a single global limit, rate limiting is scoped by action and tracked independently by IP address and email. This allows the system to respond differently to suspicious behavior without punishing legitimate users.&lt;/p&gt;
&lt;p&gt;The following flows are protected:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Login attempts.&lt;/li&gt;
&lt;li&gt;Registration attempts &lt;/li&gt;
&lt;li&gt;Forgot password requests &lt;/li&gt;
&lt;li&gt;Each flow has its own threshold, time window, and temporary block duration.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;How It Works&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For every request, the system checks whether the IP address or email is currently blocked for the given action. If either is blocked, the request is rejected immediately.&lt;/p&gt;
&lt;p&gt;On failed attempts, counters are incremented in Redis with a short TTL. Once the configured threshold is exceeded, a temporary block is applied, and the counter is cleared. Successful authentication clears any existing attempt counters.&lt;/p&gt;
&lt;p&gt;This keeps rate limiting fast, stateless, and independent of the primary database.&lt;/p&gt;
&lt;p&gt;Here’s an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;this.loginConfig = {
  maxAttempts: this.configService.get&amp;lt;number&amp;gt;('AUTH_LOGIN_MAX_ATTEMPTS', 5),
  windowMs: this.configService.get&amp;lt;number&amp;gt;('AUTH_LOGIN_WINDOW_MS', 60000),
  blockDurationMs: this.configService.get&amp;lt;number&amp;gt;('AUTH_LOGIN_BLOCK_MS',
    60000,
  ),
};

// Registration: 3 attempts per 5 minutes, blocked for 5 minutes
this.registerConfig = {
  maxAttempts: this.configService.get&amp;lt;number&amp;gt;(
    'AUTH_REGISTER_MAX_ATTEMPTS',
    3,
  ),
  windowMs: this.configService.get&amp;lt;number&amp;gt;(
      'AUTH_REGISTER_WINDOW_MS',
      300000,
  ),
  blockDurationMs: this.configService.get&amp;lt;number&amp;gt;(
      'AUTH_REGISTER_BLOCK_MS',
      300000,
    ),
};

// Forgot Password: 3 attempts per 5 minutes, blocked for 5 minutes
this.forgotPasswordConfig = {
   maxAttempts: this.configService.get&amp;lt;number&amp;gt;(
      'AUTH_FORGOT_MAX_ATTEMPTS',
      3,
   ),
   windowMs: this.configService.get&amp;lt;number&amp;gt;('AUTH_FORGOT_WINDOW_MS', 300000),
   blockDurationMs: this.configService.get&amp;lt;number&amp;gt;(
     'AUTH_FORGOT_BLOCK_MS',
     300000,
   ),
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Token Lifecycle &amp;amp; Rotation&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Access tokens in this system are intentionally short-lived. Any long-running session relies on refresh tokens, which makes the refresh flow a critical security boundary.&lt;/p&gt;
&lt;p&gt;To handle this safely, refresh tokens are rotated on every use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Refresh Flow&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When a client requests a new access token using a refresh token, the system performs the following steps inside a database transaction:&lt;/p&gt;
&lt;p&gt;Revoke the existing refresh token&lt;br&gt;
The refresh token used for the request is immediately marked as revoked. This ensures that a refresh token can only be used once.&lt;br&gt;
Re-evaluate the device context&lt;br&gt;
The request’s device information is re-derived on the backend, ensuring that the new tokens are bound to the correct deviceId.&lt;br&gt;
Issue a new token pair&lt;br&gt;
A fresh access token and refresh token are generated and returned to the client.&lt;br&gt;
Persist the new refresh token&lt;br&gt;
The new refresh token is stored in the database, replacing any existing token for the same user-device combination.&lt;br&gt;
This entire flow is executed atomically. Either all steps succeed, or none do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Why Rotation Matters&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Refresh token rotation prevents an entire class of replay attacks.&lt;/p&gt;
&lt;p&gt;If a refresh token is leaked and reused:&lt;/p&gt;
&lt;p&gt;The first request succeeds and rotates the token&lt;br&gt;
Any subsequent reuse of the old token fails because it has already been revoked&lt;br&gt;
This ensures that a compromised refresh token has a very limited window of usefulness.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Failure Behavior&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If a refresh token is revoked, expired, or does not match the stored signature for the given device, the refresh request is rejected. At that point, the client must re-authenticate.&lt;/p&gt;
&lt;p&gt;This makes refresh token misuse noisy, detectable, and self-limiting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Design Trade-off&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This approach slightly increases complexity compared to static refresh tokens, but it dramatically improves security and debuggability.&lt;/p&gt;
&lt;p&gt;Token rotation turns refresh tokens from long-lived secrets into single-use credentials, which aligns much better with production threat models.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;logout and token revocations&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Logout is handled server-side.&lt;/p&gt;
&lt;p&gt;When a user logs out:&lt;/p&gt;
&lt;p&gt;The refresh token for the current session is revoked in the database&lt;br&gt;
The cached access token for the corresponding userId and deviceId is removed from Redis&lt;br&gt;
After this, the session cannot be refreshed, and any in-flight access tokens are rejected.&lt;/p&gt;
&lt;p&gt;Logout is scoped to the current device. Other active sessions remain unaffected unless explicitly revoked.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async logout(userId: string, refreshToken: string, request: Request) {
    return await this.sequelize.transaction(async (t) =&amp;gt; {
      const dbOptions = { transaction: t };
      // Revoke refresh token in database
      await this.tokenRepository.revokeRefreshToken(
        userId,
        refreshToken,
        dbOptions,
      );

      // Clear access token from cache
      // Extract device info and clear specific device cache

      const { deviceId } = this.extractDeviceInfo(request, userId);
      deleteFromCache(userId, deviceId)

      return null;
    });
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Email Verification Token Handling&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;On events like registration, or forgot password, or a verification token is created, which is sent through email to the user. where the web passes that token along with the other information, i.e., the new password field, to change the password.&lt;/p&gt;
&lt;p&gt;These tokens live shortly in Redis; on successful request processing, these tokens are deleted, and the database is updated properly.&lt;/p&gt;
&lt;p&gt;Password reset tokens are intentionally not bound to a device. These flows are designed to work across devices and browsers, and binding them to a device context would introduce unnecessary friction without meaningful security benefits.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// a generic implementation without rate limiting, since it's getting long
 async resetPassword(email: string, token: string, newPassword: string) {
    let payload: any;
    try {
      payload = await this.jwtService.verifyAsync(token, {
        secret: this.configService.get&amp;lt;string&amp;gt;('JWT_VERIFICATION_SECRET'),
      });
    } catch {
      throwBadRequest('auth.INVALID_OR_EXPIRED_TOKEN');
    }
    if (payload.email !== email || payload.type !== 'password_reset') {
      throwBadRequest('auth.INVALID_CREDENTIALS');
    }
    const tokenSignature = token.split('.')[2];
    const cacheKey = `reset_password_token:${tokenSignature}`;
    const userId = await this.cacheManager.get&amp;lt;string&amp;gt;(cacheKey);
    if (!userId) {
      throwBadRequest('auth.INVALID_OR_EXPIRED_TOKEN');
    }
    const hashedPassword = this.hashPassword(newPassword);
    await this.usersService.updateById(userId, { password: hashedPassword });
    await this.cacheManager.del(cacheKey);
    return null;
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Closing thoughts&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
This authentication system is built around clear trade-offs rather than generic patterns. Short-lived access tokens, refresh token rotation, per-device sessions, explicit revocation, and targeted rate limiting together provide predictable behavior and reasonable security without unnecessary complexity.&lt;/p&gt;
&lt;p&gt;Follow me on X (formerly known as Twitter): &lt;a rel=&quot;nofollow&quot; href=&quot;https://x.com/Itstheanurag&quot;&gt;https://x.com/Itstheanurag&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11214/thinking-auth-in-producation-systems-a-dive-on-the-backend</guid>
<pubDate>Sat, 07 Feb 2026 15:07:52 +0000</pubDate>
</item>
<item>
<title> False Alerts in Crypto: Why Manual Verification Still Matters In today’s crypto ecosystem</title>
<link>https://coderlegion.com/8988/false-alerts-in-crypto-why-manual-verification-still-matters-in-todays-crypto-ecosystem</link>
<description>&lt;p&gt; False Alerts in Crypto: Why Manual Verification Still Matters&lt;/p&gt;
&lt;p&gt;In today’s crypto ecosystem, automated security and risk-detection systems are everywhere.&lt;br&gt;
Wallets, exchanges, and block explorers use AI and algorithms to protect users from scams.&lt;br&gt;
This is a good thing — but it is not perfect.&lt;br&gt;
Recently, our project experienced a false security alert triggered during a normal transaction.&lt;br&gt;
The system flagged it as “high risk,” even though all funds, addresses, and contracts were legitimate and verifiable on-chain.&lt;br&gt;
This is not a rare case.&lt;br&gt;
It happens when systems rely on pattern-matching instead of real blockchain context.&lt;br&gt;
 Why false alerts happen&lt;br&gt;
Most crypto security engines work like this:&lt;br&gt;
They look for similar behavior to known scams&lt;br&gt;
They check address history&lt;br&gt;
They analyze transaction patterns&lt;br&gt;
But they do not understand project structure, multisig wallets, locked liquidity, or DAO-style treasury movement.&lt;br&gt;
So when a project:&lt;br&gt;
Uses multisignature wallets&lt;br&gt;
Moves liquidity&lt;br&gt;
Executes token burns&lt;br&gt;
Or interacts with bridges&lt;br&gt;
…the system can mistakenly flag it as risky.&lt;br&gt;
️ Why manual verification is essential&lt;br&gt;
Blockchain is transparent by design.&lt;br&gt;
Anyone can verify:&lt;br&gt;
Contract ownership&lt;br&gt;
Burn addresses&lt;br&gt;
Liquidity locks&lt;br&gt;
Multisig treasuries&lt;br&gt;
On-chain transaction history&lt;br&gt;
A warning is only a signal, not proof.&lt;br&gt;
Real verification requires:&lt;br&gt;
Checking the contract on BscScan / Etherscan&lt;br&gt;
Reviewing DxLock or liquidity lockers&lt;br&gt;
Checking multisig wallets&lt;br&gt;
Reviewing GitHub, website, and docs&lt;br&gt;
This is what serious investors do.&lt;br&gt;
 What this means for investors&lt;br&gt;
A smart investor should:&lt;br&gt;
Never trust an alert blindly&lt;br&gt;
Never trust a project blindly&lt;br&gt;
Always verify on-chain&lt;br&gt;
Security systems are useful,&lt;br&gt;
but blockchain truth is stronger.&lt;br&gt;
 What this means for serious crypto projects&lt;br&gt;
Transparent projects should:&lt;br&gt;
Lock liquidity&lt;br&gt;
Use multisig wallets&lt;br&gt;
Publish on-chain proof&lt;br&gt;
Maintain public documentation&lt;br&gt;
When this is done, no automated alert can damage the truth.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/8988/false-alerts-in-crypto-why-manual-verification-still-matters-in-todays-crypto-ecosystem</guid>
<pubDate>Sat, 27 Dec 2025 17:57:28 +0000</pubDate>
</item>
<item>
<title>Why NestJS is the Future of Scalable Backend Development and Why Angular Developers Love NestJS</title>
<link>https://coderlegion.com/5666/why-nestjs-the-future-scalable-backend-development-and-why-angular-developers-love-nestjs</link>
<description>&lt;p&gt;When it comes to backend frameworks in the Node.js ecosystem, developers often debate between Express, Fastify, or rolling their own custom setup. But if you’re looking for &lt;strong&gt;scalability, maintainability, and developer productivity&lt;/strong&gt;, my money’s on &lt;strong&gt;NestJS! &lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-makes-nestjs-stand-out-&quot;&gt;What Makes NestJS Stand Out?&lt;/h3&gt;
&lt;p&gt;NestJS combines the raw performance of &lt;strong&gt;Express&lt;/strong&gt; or &lt;strong&gt;Fastify&lt;/strong&gt; with the structure of &lt;strong&gt;TypeScript decorators&lt;/strong&gt; and &lt;strong&gt;dependency injection&lt;/strong&gt;. This unique blend makes it incredibly powerful for building large-scale, enterprise-ready applications.&lt;/p&gt;
&lt;h4 id=&quot;key-features&quot;&gt;Key Features&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TypeScript-first:&lt;/strong&gt; Strong typing and modern language features out of the box.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency Injection (DI):&lt;/strong&gt; Clean, testable code with reduced boilerplate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Angular-inspired design:&lt;/strong&gt; Perfect for developers coming from Angular since it shares similar patterns like modules, services, and decorators.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modular Architecture:&lt;/strong&gt; Split your app into feature modules, making it easier to scale and maintain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GraphQL, REST, and Microservices support:&lt;/strong&gt; Build APIs and distributed systems without heavy lifting.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-angular-developers-love-nestjs&quot;&gt;Why Angular Developers Love NestJS&lt;/h3&gt;
&lt;p&gt;If you’ve worked with Angular, NestJS will feel like home. Concepts like &lt;code&gt;@Injectable()&lt;/code&gt;, &lt;code&gt;@Module()&lt;/code&gt;, and &lt;code&gt;@Controller()&lt;/code&gt; provide a familiar experience. This consistency lowers the learning curve and makes frontend and backend teams more aligned.&lt;/p&gt;
&lt;p&gt;Example of a simple controller:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Controller, Get } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get()
  findAll() {
    return ['John Doe', 'Jane Doe'];
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Minimal code, maximum clarity.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;real-world-use-cases&quot;&gt;Real-World Use Cases&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enterprise APIs:&lt;/strong&gt; Companies building scalable SaaS products use NestJS to manage complex user flows and high traffic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Microservices:&lt;/strong&gt; Native support for message brokers like Kafka, RabbitMQ, and NATS makes it ideal for distributed systems.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GraphQL Gateways:&lt;/strong&gt; With &lt;code&gt;@nestjs/graphql&lt;/code&gt;, you can quickly spin up a fully typed GraphQL API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fintech &amp;amp; Healthcare Apps:&lt;/strong&gt; The strict architecture and modularity make it easier to meet compliance and security standards.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;performance-considerations&quot;&gt;Performance Considerations&lt;/h3&gt;
&lt;p&gt;NestJS allows you to choose between &lt;strong&gt;Express&lt;/strong&gt; (widely adopted) and &lt;strong&gt;Fastify&lt;/strong&gt; (faster, lightweight) as the underlying HTTP engine. This flexibility lets teams balance between ecosystem maturity and raw performance.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;developer-experience&quot;&gt;Developer Experience&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CLI Tools:&lt;/strong&gt; Quickly scaffold controllers, services, and modules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testing:&lt;/strong&gt; Built-in utilities for unit and e2e testing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ecosystem:&lt;/strong&gt; Rich integrations with databases (TypeORM, Prisma, Mongoose), authentication libraries, and cloud services.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;NestJS isn’t just another framework—it’s a &lt;strong&gt;complete development platform&lt;/strong&gt; for Node.js. Its &lt;strong&gt;Angular-like structure&lt;/strong&gt;, &lt;strong&gt;modular architecture&lt;/strong&gt;, and &lt;strong&gt;multi-protocol support&lt;/strong&gt; make it the go-to choice for building robust backends.&lt;/p&gt;
&lt;p&gt;If you’re a developer looking to scale your skills and applications, NestJS is where you should place your bet. &lt;/p&gt;
</description>
<category>Web Dev</category>
<guid isPermaLink="true">https://coderlegion.com/5666/why-nestjs-the-future-scalable-backend-development-and-why-angular-developers-love-nestjs</guid>
<pubDate>Sat, 27 Sep 2025 08:23:15 +0000</pubDate>
</item>
<item>
<title>Why Jest with Angular?</title>
<link>https://coderlegion.com/3205/why-jest-withangular</link>
<description>&lt;hr&gt;
&lt;p&gt;To use Jest with an Angular project (instead of the default Karma + Jasmine setup), follow this structured guide to configure it properly.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;benefits&quot;&gt;Benefits&lt;/h3&gt;
&lt;p&gt;Faster test execution (especially with --runInBand and --watch).&lt;/p&gt;
&lt;p&gt;Easier debugging (rich error messages).&lt;/p&gt;
&lt;p&gt;Snapshot testing support.&lt;/p&gt;
&lt;p&gt;Widely used in React and Node.js ecosystems&lt;/p&gt;
&lt;h3 id=&quot;setup-jest&quot;&gt;setup jest&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; npm install -D jest jest-preset-angular @types/jest

&amp;gt;npm remove @types/jasmine jasmine-core karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Create 2 jest setup files&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;jest-config-js-javascript-file-&quot;&gt;jest.config.js(javascript file)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;In your project root, create /jest.config.js (.js javascript file) with the following contents.
(NOTE: The file name is reserved by jest, and jest looks up this file for configuration.)

module.exports = {
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['&amp;lt;rootDir&amp;gt;/setup-jest.ts'],
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;setup-jest-ts&quot;&gt;setup-jest.ts&lt;/h3&gt;
&lt;p&gt;In your project root, create /setup-jest.ts with the following contents.&lt;br&gt;
(INFO: You may change the filename with your preference as long as the file name is matched in the jest.config.js)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import 'jest-preset-angular/setup-jest';
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Update files&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;tsconfig-spec-json-original-file-created-by-ng-new-command-&quot;&gt;tsconfig.spec.json (Original file created by 'ng new' command.)&lt;/h3&gt;
&lt;p&gt;(1) Change types from “jasmine” to “jest”.&lt;br&gt;
(2) Remove files.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;extends&quot;: &quot;./tsconfig.json&quot;,
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;./out-tsc/spec&quot;,
    &quot;types&quot;: [&quot;jasmine&quot;]
  },
  &quot;files&quot;: [&quot;src/test.ts&quot;, &quot;src/polyfills.ts&quot;],
  &quot;include&quot;: [&quot;src/**/*.spec.ts&quot;, &quot;src/**/*.d.ts&quot;]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following is after the changes.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;extends&quot;: &quot;./tsconfig.json&quot;,
  &quot;compilerOptions&quot;: {
    &quot;outDir&quot;: &quot;./out-tsc/spec&quot;,
    &quot;types&quot;: [&quot;jest&quot;]
  },
  &quot;include&quot;: [&quot;src/**/*.spec.ts&quot;, &quot;src/**/*.d.ts&quot;]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;tsconfig-json&quot;&gt;tsconfig.json&lt;/h3&gt;
&lt;p&gt;Add “esModuleInterop”: true in the CompilorOptions to remove a warning message. (See the warning message in Appendix)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;compileOnSave&quot;: false,
  &quot;compilerOptions&quot;: {
    &quot;baseUrl&quot;: &quot;./&quot;,
    &quot;outDir&quot;: &quot;./dist/out-tsc&quot;,
    &quot;forceConsistentCasingInFileNames&quot;: true,
    &quot;strict&quot;: true,
    &quot;noImplicitReturns&quot;: true,
    &quot;noFallthroughCasesInSwitch&quot;: true,
    &quot;sourceMap&quot;: true,
    &quot;declaration&quot;: false,
    &quot;downlevelIteration&quot;: true,
    &quot;experimentalDecorators&quot;: true,
    &quot;moduleResolution&quot;: &quot;node&quot;,
    &quot;importHelpers&quot;: true,
    &quot;target&quot;: &quot;es2017&quot;,
    &quot;module&quot;: &quot;es2020&quot;,
    &quot;lib&quot;: [&quot;es2018&quot;, &quot;dom&quot;],
    &quot;esModuleInterop&quot;: true
  },
  &quot;angularCompilerOptions&quot;: {
    &quot;enableI18nLegacyMessageIdFormat&quot;: false,
    &quot;strictInjectionParameters&quot;: true,
    &quot;strictInputAccessModifiers&quot;: true,
    &quot;strictTemplates&quot;: true
  },
  &quot;types&quot;: [&quot;jest&quot;]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;package-json&quot;&gt;package.json&lt;/h3&gt;
&lt;p&gt;Change the test script from ng test to jest&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;scripts&quot;: {
  &quot;test&quot;: &quot;ng test&quot;
},==&amp;gt;&quot;scripts&quot;: {
  &quot;test&quot;: &quot;jest --coverage&quot;
},
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;remove-2-files&quot;&gt;Remove 2 files&lt;/h3&gt;
&lt;p&gt;Remove “/src/test.ts” and “/karma.config.js”.&lt;/p&gt;
&lt;h3 id=&quot;run-jest-with-coverage-option&quot;&gt;Run jest with coverage option&lt;/h3&gt;
&lt;p&gt;Run npm run test, which invokes the script “jest --coverage”&lt;/p&gt;
&lt;p&gt; Remove test object from angular.json file&lt;/p&gt;
&lt;h3 id=&quot;another-option-to-create-jest-config-files&quot;&gt;Another option to create jest config files&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;npx jest — init

&quot;test&quot;: &quot;jest --verbose&quot;,
&quot;test:coverage&quot;: &quot;jest --coverage&quot;,
&quot;test:watch&quot;: &quot;jest --watch&quot;
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Web Dev</category>
<guid isPermaLink="true">https://coderlegion.com/3205/why-jest-withangular</guid>
<pubDate>Wed, 04 Jun 2025 08:51:42 +0000</pubDate>
</item>
<item>
<title>The Hidden Truth About Booleans in .env Files: Why 'false' Is Still Truthy in JavaScript</title>
<link>https://coderlegion.com/2965/the-hidden-truth-about-booleans-in-env-files-why-false-is-still-truthy-in-javascript</link>
<description>&lt;h1&gt;Understanding Environment Variables in Node.js&lt;/h1&gt;
&lt;p&gt;In Node.js (and frameworks like NestJS), environment variables, typically managed through &lt;code&gt;.env&lt;/code&gt; files and accessed using &lt;code&gt;process.env&lt;/code&gt;, &lt;strong&gt;are always strings&lt;/strong&gt;. This subtle fact can introduce &lt;strong&gt;unexpected bugs&lt;/strong&gt;, especially when you're expecting a boolean (&lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;) but get a string (&lt;code&gt;&quot;true&quot;&lt;/code&gt; or &lt;code&gt;&quot;false&quot;&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;Real-World Example in a Node.js/NestJS Project&lt;/h2&gt;
&lt;p&gt;Suppose you have a .env file like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DB_SYNCHRONIZE=false
DB_LOGGING=true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And in your configuration code:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;database: {
  synchronize: process.env.DB_SYNCHRONIZE,
  logging: process.env.DB_LOGGING,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You expect synchronize to be false and logging to be true.&lt;br&gt;
But in reality, both will be truthy because they are non-empty strings!&lt;/p&gt;
&lt;p&gt;The Bug in Action&lt;br&gt;
Why is this a problem?&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;console.log(process.env.DB_SYNCHRONIZE); // &quot;false&quot; (string)
if (process.env.DB_SYNCHRONIZE) {
  console.log(&quot;This runs!&quot;); // This will run, even though you set it to &quot;false&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is because in JavaScript:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;false&quot; (string) is truthy&lt;/li&gt;
&lt;li&gt;Only &quot;&quot;, 0, null, undefined, and false (boolean) are falsy&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;Boolean(&quot;false&quot;); // true
Boolean(&quot;true&quot;);  // true
Boolean(&quot;&quot;)       // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, if you pass process.env.DB_SYNCHRONIZE directly to a library expecting a boolean, it will act as true!&lt;/p&gt;
&lt;p&gt;So &lt;code&gt;&quot;false&quot;&lt;/code&gt; (a non-empty string) is &lt;strong&gt;truthy&lt;/strong&gt;, and the &lt;code&gt;if&lt;/code&gt; block runs,  even though logically you set it to false!&lt;/p&gt;
&lt;p&gt;This behavior can lead to critical misconfigurations in production environments. For example, enabling logging, enabling DB synchronization (which drops and recreates tables in some ORMs), or accidentally exposing debug features.&lt;/p&gt;
&lt;p&gt;Always convert environment variable strings to booleans explicitly.&lt;/p&gt;
&lt;h2&gt;The Correct Approach: Explicit Type Conversion&lt;/h2&gt;
&lt;h2&gt;Boolean Conversion Pattern&lt;/h2&gt;
&lt;p&gt;Always parse environment variables to their expected types before use.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;const synchronize = process.env.DB_SYNCHRONIZE === 'true';
const logging = process.env.DB_LOGGING === 'true';
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This way:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;'true' === 'true'&lt;/code&gt; → &lt;code&gt;true&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;'false' === 'true'&lt;/code&gt; → &lt;code&gt;false&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You now get predictable, safe boolean values.&lt;/p&gt;
&lt;h2&gt;Optional Utility Function&lt;/h2&gt;
&lt;p&gt;For larger projects, it's wise to create a helper:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;function toBool(value: string | undefined): boolean {
  return value?.toLowerCase() === 'true';
}

const synchronize = toBool(process.env.DB_SYNCHRONIZE);
const logging = toBool(process.env.DB_LOGGING);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Pro Tip: Use a Config Validation Library&lt;/h2&gt;
&lt;p&gt;Frameworks like NestJS recommend using a validation layer (e.g., with &lt;code&gt;Joi&lt;/code&gt; or &lt;code&gt;zod&lt;/code&gt;) to validate and transform config values at startup.&lt;/p&gt;
&lt;p&gt;Example using &lt;code&gt;Joi&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;const configSchema = Joi.object({
  DB_SYNCHRONIZE: Joi.boolean().default(false),
  DB_LOGGING: Joi.boolean().default(false),
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Real-Life Pitfall: When &quot;false&quot; Isn’t Really False&lt;/h2&gt;
&lt;p&gt;This isn’t just theory, I ran into this issue myself while working on a NestJS project using TypeORM.&lt;/p&gt;
&lt;p&gt;I had this in my .env:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;DB_SYNCHRONIZE=false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And my config looked like:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;synchronize: process.env.DB_SYNCHRONIZE,
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I assumed this would disable TypeORM’s automatic schema synchronization, since I planned to use migrations instead.&lt;/p&gt;
&lt;p&gt;But when I started the app, the tables were still being created. Then, when I tried to generate a migration:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;typeorm migration:generate -n AddNewFields
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I kept seeing:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;No changes in database schema were found - cannot generate a migration.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It was confusing, until I logged the value of process.env.DB_SYNCHRONIZE and saw:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;console.log(typeof process.env.DB_SYNCHRONIZE); // string
console.log(process.env.DB_SYNCHRONIZE);        // &quot;false&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That string &quot;false&quot; is truthy, so synchronize: &quot;false&quot; is effectively treated as true in JavaScript. TypeORM was happily syncing the schema on every run, and by the time I tried to run the migration generator, there were no changes left to detect.&lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Misinterpreting environment variables is one of those bugs that can sneak into production unnoticed until something critical misbehaves. In systems where flags control behavior like syncing databases, enabling debug logs, or toggling features, treating &lt;code&gt;&quot;false&quot;&lt;/code&gt; as a boolean without conversion can be dangerous.&lt;/p&gt;
&lt;p&gt;Always treat &lt;code&gt;process.env&lt;/code&gt; values as &lt;strong&gt;untrusted strings&lt;/strong&gt; and explicitly cast them to the types your logic expects. Doing this upfront helps you avoid fragile assumptions and keeps your config layer predictable.&lt;/p&gt;
</description>
<category>Best Practices</category>
<guid isPermaLink="true">https://coderlegion.com/2965/the-hidden-truth-about-booleans-in-env-files-why-false-is-still-truthy-in-javascript</guid>
<pubDate>Sun, 11 May 2025 15:49:03 +0000</pubDate>
</item>
<item>
<title>Grasping the different Solana clusters—Devnet, Testnet, and Mainnet—is essential for efficient development.</title>
<link>https://coderlegion.com/1111/grasping-different-solana-clusters-devnet-testnet-mainnet-essential-efficient-development</link>
<description>&lt;h3 id=&quot;what-are-solana-clusters-and-how-to-work-with-devnet-testnet-and-mainnet-&quot;&gt;What Are Solana Clusters, and How to Work with Devnet, Testnet, and Mainnet?&lt;/h3&gt;
&lt;p&gt;Solana is a high-performance blockchain known for its fast transaction speeds and scalability. One of the core concepts developers need to understand when working with Solana is the &lt;strong&gt;cluster&lt;/strong&gt;. Solana clusters are distinct environments that provide different functionalities for developing, testing, and deploying blockchain applications. In this article, we’ll dive into what Solana clusters are, how they differ from each other, and how developers can leverage &lt;strong&gt;Devnet&lt;/strong&gt;, &lt;strong&gt;Testnet&lt;/strong&gt;, and &lt;strong&gt;Mainnet&lt;/strong&gt; to create robust applications.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-are-solana-clusters-&quot;&gt;What Are Solana Clusters?&lt;/h3&gt;
&lt;p&gt;A &lt;strong&gt;cluster&lt;/strong&gt; in Solana refers to a network of validators working together to validate transactions and maintain the integrity of the blockchain. There are three main clusters in Solana: &lt;strong&gt;Devnet&lt;/strong&gt;, &lt;strong&gt;Testnet&lt;/strong&gt;, and &lt;strong&gt;Mainnet&lt;/strong&gt;. Each cluster is designed for a specific stage in the development lifecycle.&lt;/p&gt;
&lt;h4 id=&quot;key-cluster-types-in-solana&quot;&gt;Key Cluster Types in Solana&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Devnet&lt;/strong&gt;: A testing environment where developers can experiment freely without real consequences.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testnet&lt;/strong&gt;: A staging environment designed to simulate real-world conditions, closer to the Mainnet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mainnet&lt;/strong&gt;: The live Solana blockchain where real transactions happen and real-world value is at stake.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&quot;understanding-each-solana-cluster&quot;&gt;Understanding Each Solana Cluster&lt;/h3&gt;
&lt;h4 id=&quot;devnet-the-developer-playground&quot;&gt;&lt;strong&gt;Devnet: The Developer Playground&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Devnet&lt;/strong&gt; is Solana's sandbox where developers can test their applications, smart contracts, and blockchain interactions without using real tokens or risking any assets.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Devnet is used for early-stage development and experimentation. Developers can test smart contracts, deploy decentralized apps (dApps), and learn Solana’s programming environment without fear of financial loss.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Supply&lt;/strong&gt;: Devnet provides free tokens (often called dev tokens) that can be used for testing but hold no real-world value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No transaction costs&lt;/li&gt;
&lt;li&gt;Free tokens for testing&lt;/li&gt;
&lt;li&gt;Ideal for quick testing and prototyping&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example Command&lt;/strong&gt;:&lt;br&gt;
To switch to Devnet, use the Solana CLI:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```bash
solana config set --url devnet
```
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;testnet-simulating-real-world-scenarios&quot;&gt;&lt;strong&gt;Testnet: Simulating Real-World Scenarios&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Testnet&lt;/strong&gt; is a more realistic environment that mimics Mainnet conditions. It’s used for thorough testing, ensuring that your applications can scale and perform under conditions similar to the production environment.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: &lt;strong&gt;Testnet&lt;/strong&gt; is used to simulate the real world and identify any issues before deploying your code to Mainnet. While it’s not a live environment, Testnet closely mirrors the actual blockchain conditions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Supply&lt;/strong&gt;: Like Devnet, &lt;strong&gt;Testnet&lt;/strong&gt; uses tokens that are free but do not hold any real value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simulates real-world usage&lt;/li&gt;
&lt;li&gt;Tests how applications will scale in production&lt;/li&gt;
&lt;li&gt;Available for testing interactions with other projects in the Solana ecosystem&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example Command&lt;/strong&gt;:&lt;br&gt;
Switch to Testnet with the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```bash
solana config set --url testnet
```
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;mainnet-live-blockchain-for-real-world-use&quot;&gt;&lt;strong&gt;Mainnet: Live Blockchain for Real-World Use&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;The &lt;strong&gt;Mainnet&lt;/strong&gt; is the live blockchain network. This is where real transactions occur, and developers deploy their finalized, production-ready applications. Any transactions on Mainnet involve actual assets with real-world value.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Mainnet is used for deploying applications after they have been thoroughly tested on Devnet and Testnet. Once your application is ready for public use, it’s deployed here.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token Supply&lt;/strong&gt;: Mainnet uses &lt;strong&gt;SOL&lt;/strong&gt; tokens, which have real monetary value and are used for paying transaction fees and staking.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Real transactions with actual SOL tokens&lt;/li&gt;
&lt;li&gt;Deploy production-ready applications&lt;/li&gt;
&lt;li&gt;Live usage by end users&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example Command&lt;/strong&gt;:&lt;br&gt;
Switch to Mainnet with this command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;```bash
solana config set --url mainnet
```
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;how-to-work-with-different-solana-clusters-effectively&quot;&gt;How to Work with Different Solana Clusters Effectively&lt;/h3&gt;
&lt;h4 id=&quot;1-start-with-devnet-&quot;&gt;&lt;strong&gt;1. Start with Devnet&lt;/strong&gt;:&lt;/h4&gt;
&lt;p&gt;Begin your development on Devnet to experiment with Solana’s features without worrying about costs or real consequences. It’s the best place to develop new smart contracts and dApps.&lt;/p&gt;
&lt;h4 id=&quot;2-move-to-testnet-for-testing-&quot;&gt;&lt;strong&gt;2. Move to Testnet for Testing&lt;/strong&gt;:&lt;/h4&gt;
&lt;p&gt;Once your application is stable on Devnet, deploy it to &lt;strong&gt;Testnet&lt;/strong&gt;. Testnet helps you simulate real-world conditions and identify any performance or scalability issues.&lt;/p&gt;
&lt;h4 id=&quot;3-deploy-to-mainnet-&quot;&gt;&lt;strong&gt;3. Deploy to Mainnet&lt;/strong&gt;:&lt;/h4&gt;
&lt;p&gt;After testing your app in Devnet and Testnet, you’re ready for &lt;strong&gt;Mainnet&lt;/strong&gt;. This is the live environment where your users will interact with your application.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=5255646752472752493&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In Solana, understanding and utilizing the different clusters—&lt;strong&gt;Devnet&lt;/strong&gt;, &lt;strong&gt;Testnet&lt;/strong&gt;, and &lt;strong&gt;Mainnet&lt;/strong&gt;—is crucial for ensuring the success of your blockchain project. &lt;strong&gt;Devnet&lt;/strong&gt; is where you begin development, &lt;strong&gt;Testnet&lt;/strong&gt; allows you to simulate real-world scenarios, and &lt;strong&gt;Mainnet&lt;/strong&gt; is where your final, production-ready application goes live. By following the right progression and using each environment to its strengths, you can avoid costly mistakes and ensure that your application performs well under real-world conditions.&lt;/p&gt;
&lt;p&gt;By following best practices and leveraging Solana’s clusters effectively, developers can streamline their workflow, ensuring smoother transitions from development to production.&lt;/p&gt;
&lt;p&gt;Feel free to leave a comment or share your thoughts below – we'd love to hear how you’re using Solana clusters in your projects!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://solana.com/&quot;&gt;Solana Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://docs.solana.com/clusters&quot;&gt;Solana Cluster Overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
<category>Containerization</category>
<guid isPermaLink="true">https://coderlegion.com/1111/grasping-different-solana-clusters-devnet-testnet-mainnet-essential-efficient-development</guid>
<pubDate>Tue, 11 Feb 2025 22:12:27 +0000</pubDate>
</item>
<item>
<title>Advanced Strategies: How to Implement the Strategy Pattern in Your NestJS Projects</title>
<link>https://coderlegion.com/966/advanced-strategies-how-to-implement-the-strategy-pattern-in-your-nestjs-projects</link>
<description>&lt;p&gt;One of the design patterns that caught my attention the most when learning TypeScript was the Strategy Pattern. Although it's not exclusive to TypeScript, this pattern significantly enriches the code by promoting reusability and decoupling.&lt;/p&gt;
&lt;h3 id=&quot;what-does-the-pattern-consist-of-&quot;&gt;What does the pattern consist of?&lt;/h3&gt;
&lt;p&gt;The Strategy Pattern allows a class to modify the algorithm or behavior it uses during execution. This is achieved by defining a series of algorithms, each encapsulated in its own class and following a common interface. This way, behaviors can be easily interchanged without the need to alter the class that implements them.&lt;/p&gt;
&lt;h3 id=&quot;a-real-life-example&quot;&gt;A real-life example&lt;/h3&gt;
&lt;p&gt;Imagine an application that sends notifications to users, with variable notification methods, such as email, SMS, or push notifications. Instead of coding a single sending method, your application can adopt different notification strategies according to the needs of the moment. This is achieved by implementing a common interface for notification strategies, ensuring that your application knows how to send them, regardless of the chosen method. This approach allows you to easily change notification methods without affecting the overall functioning of the application. At first it sounds a bit confusing, so let's better go to an example with code.&lt;/p&gt;
&lt;h3 id=&quot;code-where-the-strategy-pattern-is-not-being-used&quot;&gt;Code where the Strategy Pattern is not being used&lt;/h3&gt;
&lt;p&gt;In the context of the previous example and using NestJS, let's consider the &lt;code&gt;NotificationService&lt;/code&gt;. This service is responsible for sending different types of notifications, selecting the appropriate method based on an argument passed to the &lt;code&gt;notify&lt;/code&gt; method. The selection of the notification method is done through conditionals, determining whether to send an email, SMS, or push notification depending on the case:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import { Injectable } from '@nestjs/common';

@Injectable()
export class NotificationService {
  async notify(user: User, message: string, method: string): Promise&amp;lt;void&amp;gt; {
    if (method === 'email') {
      console.log(`Sending email to ${user.email}: ${message}`);
      // Logic to send email
    } else if (method === 'sms') {
      console.log(`Sending SMS to ${user.phone}: ${message}`);
      // Logic to send sms
    } else if (method === 'push') {
      console.log(`Sending push notification: ${message}`);
      // Logic ton send push notification
    } else {
      throw new Error('Invalid notification method');
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The following code fragment demonstrates how we would use the &lt;code&gt;NotificationService&lt;/code&gt; to send two notifications, one by email and another by SMS. In this scenario, the notification method is decided at runtime, which shows the flexibility of our service to adapt to different notification requirements:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;export class AppService {
  constructor(private readonly notificationService: NotificationService) {}

  async sendNotification() {
    const user = { email: '*Emails are not allowed*', phone: '+1234567890' };
    const message = 'This is a test message.';

    // Choose the method in execution time
    await this.notificationService.notify(user, message, 'email');
    await this.notificationService.notify(user, message, 'sms');
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach reveals several significant disadvantages that deserve attention:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;High Coupling: The selection and execution of notification methods are tightly integrated within a single class or function, complicating code management and expansion. This high degree of coupling reduces flexibility and increases maintenance complexity.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Violation of the Open/Closed Principle (OCP): Incorporating a new notification method involves directly modifying the NotificationService class, adding more conditions. This contravenes the OCP principle, according to which software entities should allow their extension without the need to modify their existing content, thus promoting greater scalability and maintainability.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing Complexity: Verifying the correct functioning of NotificationService becomes more arduous. Each condition needs to be tested individually to confirm its operability, increasing the effort and complexity of testing.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;refactoring-the-code&quot;&gt;Refactoring the code&lt;/h3&gt;
&lt;p&gt;To apply the Strategy pattern in our refactoring of &lt;code&gt;NotificationService&lt;/code&gt;, we'll remove the conditionals from the class. Instead, we'll modify the class to accept an object through its constructor. This object must adhere to a specific interface that includes a &lt;code&gt;send&lt;/code&gt; method. This method will be responsible for executing the sending logic for the corresponding notification type, thus allowing &lt;code&gt;NotificationService&lt;/code&gt; to delegate the responsibility of sending the notification, decoupling the service from the specific implementation details of each sending method. In this way, &lt;code&gt;NotificationService&lt;/code&gt; acts merely as a context for sending notifications, without being tied to any particular sending method.&lt;/p&gt;
&lt;p&gt;We'll start by defining the common interface that all objects intended to be used as notification strategies must fulfill. This interface ensures that any notification strategy provides an implementation of the &lt;code&gt;send&lt;/code&gt; method, which is responsible for executing the specific notification sending logic.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// notification.strategy.interface.ts
export interface NotificationStrategy {
  send(user: User, message: string): Promise&amp;lt;void&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After defining the &lt;code&gt;NotificationStrategy&lt;/code&gt; interface, we proceed to integrate it into our &lt;code&gt;NotificationService&lt;/code&gt;. This change involves adjusting the &lt;code&gt;NotificationService&lt;/code&gt; constructor to accept an object that implements &lt;code&gt;NotificationStrategy&lt;/code&gt;. By doing this, we eliminate the need for conditionals within the service, delegating the responsibility of the sending logic to the &lt;code&gt;send&lt;/code&gt; method of the injected strategy object. The service's &lt;code&gt;notify&lt;/code&gt; function is therefore significantly simplified, limiting itself to invoking send on the provided strategy.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// notification.service.ts
import { Injectable } from '@nestjs/common';
import { NotificationStrategy } from './notification.strategy.interface';

@Injectable()
export class NotificationService {

  constructor(private strategy: NotificationStrategy) {}

  async notify(user: User, message: string): Promise&amp;lt;void&amp;gt; {
    await this.strategy.send(user, message);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, to complete our implementation of the strategy pattern, we create different types of notification strategies that &lt;code&gt;NotificationService&lt;/code&gt; can use. Specifically, we will develop &lt;code&gt;EmailNotificationStrategy&lt;/code&gt; and &lt;code&gt;SmsNotificationStrategy&lt;/code&gt;, each with its respective &lt;code&gt;send&lt;/code&gt; method. These concrete strategies encapsulate the specific logic for sending notifications via email and SMS, respectively.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// email.notification.strategy.ts
import { NotificationStrategy } from './notification.strategy.interface';
import { Injectable } from '@nestjs/common';

@Injectable()
export class EmailNotificationStrategy implements NotificationStrategy {
  async send(user: User, message: string): Promise&amp;lt;void&amp;gt; {
    console.log(`Sending email to ${user.email}: ${message}`);
    // here the logic to send email
  }
}

// sms.notification.strategy.ts
import { NotificationStrategy } from './notification.strategy.interface';
import { Injectable } from '@nestjs/common';

@Injectable()
export class SmsNotificationStrategy implements NotificationStrategy {
  async send(user: User, message: string): Promise&amp;lt;void&amp;gt; {
    console.log(`Sending SMS to ${user.phone}: ${message}`);
    // here the logic to send SMS
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To maximize the flexibility of &lt;code&gt;NotificationService&lt;/code&gt; and allow it to change its notification strategy at runtime, we introduce a setter method, &lt;code&gt;setStrategy&lt;/code&gt;. This method allows updating the notification strategy used by NotificationService, facilitating adaptation to different needs without compromising the current instance of the service.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// notification.service.ts
import { Injectable } from '@nestjs/common';
import { NotificationStrategy } from './notification.strategy.interface';

@Injectable()
export class NotificationService {

  constructor(private strategy: NotificationStrategy) {}

  setStrategy(strategy: NotificationStrategy) {
    this.strategy = strategy;
  }

  async notify(user: User, message: string): Promise&amp;lt;void&amp;gt; {
    await this.strategy.send(user, message);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the implementation of the strategy pattern in our notification system, we have demonstrated how code flexibility and maintainability can be significantly increased. The following example illustrates how &lt;code&gt;AppService&lt;/code&gt; can dynamically change the notification strategy from &lt;code&gt;EmailNotificationStrategy&lt;/code&gt; to &lt;code&gt;SmsNotificationStrategy&lt;/code&gt;, adapting to different notification needs at runtime:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// app.service.ts
import { Injectable } from '@nestjs/common';
import { NotificationService } from './notification.service';
import { EmailNotificationStrategy } from './email.notification.strategy';
import { SmsNotificationStrategy } from './sms.notification.strategy';

@Injectable()
export class AppService {
  constructor(
    private readonly notificationService: NotificationService,
    private readonly emailStrategy: EmailNotificationStrategy,
    private readonly smsStrategy: SmsNotificationStrategy,
  ) {}

  async sendNotification() {
    const user = { email: '*Emails are not allowed*', phone: '+1234567890' };
    const message = 'This is a test message.';

    // Cambiar estrategia según el contexto
    this.notificationService.setStrategy(this.emailStrategy);
    await this.notificationService.notify(user, message);

    // Cambiar a SMS
    this.notificationService.setStrategy(this.smsStrategy);
    await this.notificationService.notify(user, message);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This approach not only validates the versatility of the strategy pattern but also underlines its value in creating modular and extensible applications. By separating notification logic into concrete and interchangeable strategies, we facilitate the addition of new notification methods and improve the system's testability. Furthermore, we adhere to the open/closed principle, allowing our system to evolve with minimal changes to existing code.&lt;/p&gt;
&lt;p&gt;In summary, the application of the strategy pattern in notification management in TypeScript with NestJS demonstrates how software design principles can be put into practice to build robust, flexible, and maintainable systems. The ability to change strategies at runtime not only enriches our application with operational flexibility but also highlights the importance of forward-thinking software design.&lt;/p&gt;
</description>
<category>Best Practices</category>
<guid isPermaLink="true">https://coderlegion.com/966/advanced-strategies-how-to-implement-the-strategy-pattern-in-your-nestjs-projects</guid>
<pubDate>Wed, 29 Jan 2025 10:14:17 +0000</pubDate>
</item>
<item>
<title>Why NestJS Is The New Gold Standard For Node Backend Development</title>
<link>https://coderlegion.com/805/why-nestjs-is-the-new-gold-standard-for-node-backend-development</link>
<description>&lt;p&gt;As a Node.js developer who has tried every Node framework under the sun, here’s why I believe NestJS must be the new gold standard for Node.js backend development. At first, the framework seemed like too much—the learning curve was steep, and I found it hard to understand coming from Express. Why all this complexity? But with time, I came to admire every aspect of this framework.&lt;/p&gt;
&lt;h3 id=&quot;1-why-oop-is-the-best-for-backend-development&quot;&gt;1. &lt;strong&gt;Why OOP is the Best for Backend Development&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Object-Oriented Programming (OOP) is not just a paradigm; it's a methodology that addresses the core challenges of backend development. At its heart, OOP allows you to model real-world problems in a way that makes systems easier to design, implement, and maintain. NestJS utilizes OOP through its class-based approach, enabling you to organize logic into cohesive, reusable components.&lt;/p&gt;
&lt;p&gt;For instance, consider the concept of services in NestJS. A service class encapsulates business logic, promoting separation of concerns. This encapsulation not only makes your codebase easier to navigate but also simplifies testing. Using decorators like &lt;code&gt;@Injectable()&lt;/code&gt;, NestJS takes dependency injection a step further, allowing seamless integration of service dependencies without manual wiring.&lt;/p&gt;
&lt;h4 id=&quot;code-example&quot;&gt;Code Example&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Injectable } from '@nestjs/common';

@Injectable()
export class UserService {
  private users = [];

  createUser(name: string) {
    const user = { id: Date.now(), name };
    this.users.push(user);
    return user;
  }

  getUsers() {
    return this.users;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Moreover, inheritance in OOP allows developers to extend and reuse functionality without duplicating code. Polymorphism, another cornerstone of OOP, lets you define common interfaces for varying implementations. In a NestJS context, this could be seen in abstract classes for database repositories, where specific implementations handle details for MongoDB, PostgreSQL, or other data stores.&lt;/p&gt;
&lt;p&gt;So as your codebase grows larger, you can maintain a well-structured codebase within every module.&lt;/p&gt;
&lt;h3 id=&quot;2-nestjs-is-future-proof&quot;&gt;2. &lt;strong&gt;NestJS is Future-Proof&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;NestJS positions itself as a framework built to withstand the test of time. Its adoption of TypeScript ensures that your code is reliable and maintainable.&lt;/p&gt;
&lt;p&gt;NestJS also uses decorators extensively, aligning with modern JavaScript standards such as ES6+ and ECMAScript proposals. These decorators, like &lt;code&gt;@Controller()&lt;/code&gt;, &lt;code&gt;@Get()&lt;/code&gt;, and &lt;code&gt;@Post()&lt;/code&gt;, provide declarative syntax that makes code intuitive and reduces boilerplate.&lt;/p&gt;
&lt;h4 id=&quot;code-example-1&quot;&gt;Code Example&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Controller, Get } from '@nestjs/common';

@Controller('users')
export class UserController {
  @Get()
  findAll() {
    return 'This action returns all users';
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-ideal-for-microservices-and-enterprise-applications&quot;&gt;3. &lt;strong&gt;Ideal for Microservices and Enterprise Applications&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;NestJS shines in environments where modularity and scalability are non-negotiable. For microservices, NestJS provides native support for distributed systems using patterns like message brokers and event-driven communication. The framework includes modules for integration with RabbitMQ, Kafka, and Redis, making it easy to design resilient and decoupled systems.&lt;/p&gt;
&lt;h4 id=&quot;code-example-2&quot;&gt;Code Example&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';

@Controller()
export class AppController {
  @MessagePattern('notifications')
  handleNotification(data: any) {
    console.log('Received notification:', data);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For enterprise-grade applications, NestJS's modular architecture allows teams to work on isolated modules without stepping on each other’s toes. Features like &lt;code&gt;DynamicModule&lt;/code&gt; allow you to configure modules dynamically, simplifying the management of multi-tenant systems or applications with environment-specific configurations.&lt;/p&gt;
&lt;h3 id=&quot;4-built-in-support-for-everything&quot;&gt;4. Built-in Support for Everything&lt;/h3&gt;
&lt;p&gt;NestJS eliminates the need for cobbling together third-party libraries by offering built-in support for a wide array of features. Need WebSocket support for real-time applications? NestJS provides an out-of-the-box module for that. Building a GraphQL API? NestJS's GraphQL module integrates seamlessly with decorators for schema-first or code-first approaches.&lt;/p&gt;
&lt;h4 id=&quot;code-example-3&quot;&gt;Code Example&lt;/h4&gt;
&lt;p&gt;Integrating JWT authentication using Passport.js:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Injectable } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { Strategy, ExtractJwt } from 'passport-jwt';

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: 'secretKey',
    });
  }

  validate(payload: any) {
    return { userId: payload.sub, username: payload.username };
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For authentication, the &lt;code&gt;@nestjs/passport&lt;/code&gt; library integrates Passport.js directly into your project, providing strategies for OAuth, JWT, and local authentication. NestJS also simplifies database interaction with its &lt;code&gt;@nestjs/typeorm&lt;/code&gt; and &lt;code&gt;@nestjs/mongoose&lt;/code&gt; modules, providing tight integration with popular ORMs like TypeORM and Mongoose.&lt;/p&gt;
&lt;p&gt;This all-inclusive approach reduces decision fatigue and ensures consistency across your application, allowing you to focus on solving business problems rather than configuring your stack.&lt;/p&gt;
&lt;h3 id=&quot;5-modular-architecture-that-scales&quot;&gt;5. &lt;strong&gt;Modular Architecture That Scales&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;NestJS’s modular system is a game-changer for large-scale applications. By encapsulating features into dedicated modules, it allows developers to maintain clean boundaries between different parts of the application. Each module in NestJS acts as a self-contained unit, bundling together controllers, services, and other components.&lt;/p&gt;
&lt;h4 id=&quot;code-example-4&quot;&gt;Code Example&lt;/h4&gt;
&lt;p&gt;Creating a user module:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';

@Module({
  controllers: [UserController],
  providers: [UserService],
})
export class UserModule {}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The modular design allows you to separate concerns and easily scale your application by adding new modules.&lt;/p&gt;
&lt;p&gt;NestJS also supports lazy loading of modules, a crucial feature for microservices or applications with large, complex dependencies. This ensures that your application starts faster and consumes fewer resources.&lt;/p&gt;
&lt;h3 id=&quot;6-very-hard-to-mess-up-in-nestjs&quot;&gt;6. &lt;strong&gt;Very Hard to Mess Up in NestJS&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;NestJS offers guardrails that make it difficult to write bad code. Its opinionated structure enforces best practices, such as the separation of concerns, dependency injection, and modular design. The framework's CLI (&lt;code&gt;@nestjs/cli&lt;/code&gt;) helps scaffold components with a consistent folder structure, eliminating the guesswork in organizing your codebase.&lt;/p&gt;
&lt;h4 id=&quot;code-example-5&quot;&gt;Code Example&lt;/h4&gt;
&lt;p&gt;Using guards for role-based access control:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';

@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    return user &amp;amp;&amp;amp; user.roles.includes('admin');
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Additionally, NestJS makes full use of TypeScript to catch errors during development, reducing runtime bugs. Features like guards (&lt;code&gt;@CanActivate&lt;/code&gt;), interceptors (&lt;code&gt;@Interceptor()&lt;/code&gt;), and pipes (&lt;code&gt;@PipeTransform&lt;/code&gt;) provide clear patterns for handling concerns like validation, transformation, and access control. This layered approach ensures that even junior developers can contribute effectively while adhering to established conventions.&lt;/p&gt;
&lt;p&gt;Even error handling is simplified. By extending the built-in &lt;code&gt;HttpException&lt;/code&gt;, you can create custom exceptions with ease, ensuring your APIs remain consistent and predictable. NestJS takes care of the rest, including sending the appropriate HTTP response codes and error messages.&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;final-thoughts-1&quot;&gt;Final Thoughts&lt;/h4&gt;
&lt;p&gt;NestJS isn’t just another Node.js framework; it’s a paradigm shift in backend development. It’s an ideal choice, offering everything you need to succeed. From my experience, I believe this framework strikes the perfect balance between rapid delivery and long-term maintainability. It represents the ultimate evolution of Node.js backend development, setting a new standard for scalability and efficiency.&lt;br&gt;
For more in-depth insights, check out the book &lt;strong&gt;Scalable Application Development with NestJS&lt;/strong&gt;, available &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.packtpub.com/en-us/product/scalable-application-development-with-nestjs-9781835463956?utm_medium=affiliate&amp;amp;utm_campaign=1609a0e8-a37d-c05e-295c-6780c796351a&amp;amp;utm_term=e2025f61-d111-eb11-a812-00224801bc77&amp;amp;utm_content=B21694&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</description>
<category>TypeScript</category>
<guid isPermaLink="true">https://coderlegion.com/805/why-nestjs-is-the-new-gold-standard-for-node-backend-development</guid>
<pubDate>Tue, 14 Jan 2025 12:39:58 +0000</pubDate>
</item>
</channel>
</rss>