<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ backend - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ backend - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 02 Jun 2026 17:10:39 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/backend/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ From Flutter to Backend: How to Build Production-Grade REST APIs with Dart and Serverpod ]]>
                </title>
                <description>
                    <![CDATA[ Serverpod is one of the most performant backend frameworks built on Dart. It's a fully opinionated backend framework that comes with its own ORM, its own code generation system, migration tooling, aut ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-production-grade-rest-apis-with-dart-and-serverpod/</link>
                <guid isPermaLink="false">6a1f040ecf96043972a543a7</guid>
                
                    <category>
                        <![CDATA[ Serverpod ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Server side rendering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Dart ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwaseyi Fatunmole ]]>
                </dc:creator>
                <pubDate>Tue, 02 Jun 2026 16:25:50 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/910a29c7-b380-4432-bc3c-d2c6930c3ac9.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Serverpod is one of the most performant backend frameworks built on Dart. It's a fully opinionated backend framework that comes with its own ORM, its own code generation system, migration tooling, authentication module, and deployment platform.</p>
<p>If you use a tool like Shelf to build your API, you assemble everything yourself. You choose your packages, write your own middleware, manage your own database connection, and wire every piece together manually. That's the Shelf way, and it teaches you exactly how server-side Dart works under the hood.</p>
<p>Serverpod is a different philosophy entirely.</p>
<p>Where Shelf gives you primitives, Serverpod gives you a complete system. You define your models in YAML, run a generator, and get fully typed database classes, serialization, and client-side code produced automatically.</p>
<p>For Flutter engineers, this feels immediately familiar. It's the same kind of productivity you get from the Flutter toolchain itself, applied to the backend.</p>
<p>In this article, we're going to build a User and Profile Management REST API from scratch using Serverpod. You'll learn how Serverpod's code generation, built-in ORM, and endpoint system work, and you'll have a fully deployed backend by the end.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-how-serverpod-differs-from-shelf">How Serverpod Differs from Shelf</a></p>
</li>
<li><p><a href="#heading-installing-serverpod">Installing Serverpod</a></p>
</li>
<li><p><a href="#heading-creating-the-project">Creating the Project</a></p>
</li>
<li><p><a href="#heading-understanding-the-project-structure">Understanding the Project Structure</a></p>
</li>
<li><p><a href="#heading-serverpod-core-concepts">Serverpod Core Concepts</a></p>
<ul>
<li><p><a href="#heading-endpoints-and-the-session-object">Endpoints and the Session Object</a></p>
</li>
<li><p><a href="#heading-model-files-and-code-generation">Model Files and Code Generation</a></p>
</li>
<li><p><a href="#heading-the-built-in-orm">The Built-in ORM</a></p>
</li>
<li><p><a href="#heading-migrations">Migrations</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-starting-the-development-server">Starting the Development Server</a></p>
</li>
<li><p><a href="#heading-defining-the-models">Defining the Models</a></p>
<ul>
<li><p><a href="#heading-the-user-model">The User Model</a></p>
</li>
<li><p><a href="#heading-the-profile-model">The Profile Model</a></p>
</li>
<li><p><a href="#heading-running-code-generation">Running Code Generation</a></p>
</li>
<li><p><a href="#heading-creating-and-applying-migrations">Creating and Applying Migrations</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-building-the-api">Building the API</a></p>
<ul>
<li><p><a href="#heading-the-auth-endpoint">The Auth Endpoint</a></p>
</li>
<li><p><a href="#heading-the-user-endpoint">The User Endpoint</a></p>
</li>
<li><p><a href="#heading-the-profile-endpoint">The Profile Endpoint</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-authentication">Authentication</a></p>
<ul>
<li><p><a href="#heading-password-hashing-and-jwt">Password Hashing and JWT</a></p>
</li>
<li><p><a href="#heading-protecting-endpoints">Protecting Endpoints</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-error-handling-in-serverpod">Error Handling in Serverpod</a></p>
</li>
<li><p><a href="#heading-testing-the-api">Testing the API</a></p>
</li>
<li><p><a href="#heading-deployment">Deployment</a></p>
<ul>
<li><p><a href="#heading-deploying-with-docker-and-flyio">Deploying with Docker and Fly.io</a></p>
</li>
<li><p><a href="#heading-deploying-with-serverpod-cloud">Deploying with Serverpod Cloud</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before starting, you should have:</p>
<ul>
<li><p>Familiarity with Dart and Flutter development</p>
</li>
<li><p>Understanding of REST API concepts, endpoints, HTTP methods, status codes</p>
</li>
<li><p>Docker Desktop installed and running</p>
</li>
<li><p>Flutter SDK installed (Serverpod requires it even for server-only projects)</p>
</li>
<li><p>A Fly.io account or a Serverpod Cloud account for deployment</p>
</li>
</ul>
<h2 id="heading-how-serverpod-differs-from-shelf">How Serverpod Differs from Shelf</h2>
<p>Before writing a single line of code, it's worth understanding the fundamental difference in philosophy between Shelf and Serverpod. This will make every design decision in the framework feel deliberate rather than arbitrary.</p>
<p>With Shelf, you write everything. Request parsing, response formatting, database queries, migrations, auth, and logging. Every piece is explicit code that you understand because you wrote it.</p>
<p>With Serverpod, you define things and the framework writes code for you. You define a model in YAML, run serverpod generate, and get a full Dart class with database bindings, serialization, and client-side access automatically. You define an endpoint method, and the framework handles routing, parameter extraction, and response formatting.</p>
<p>This is the same trade-off Flutter makes compared to building with raw platform APIs. Flutter writes the layout engine, the rendering pipeline, and the gesture system for you. You focus on your product logic. Serverpod makes the same bet on the backend.</p>
<p>The cost of that productivity is flexibility. Serverpod has strong opinions about how things should be structured. If your use case fits those opinions, development is extremely fast. If it doesn't, you're working against the framework.</p>
<p>For the User and Profile Management API we're building here, Serverpod is a very good fit.</p>
<h2 id="heading-installing-serverpod">Installing Serverpod</h2>
<p>Serverpod requires Flutter to be installed, even for server-only work. This is because its toolchain builds client packages alongside the server package during project creation.</p>
<p>Install the Serverpod CLI globally:</p>
<pre><code class="language-bash">dart pub global activate serverpod_cli
</code></pre>
<p>Verify the installation:</p>
<pre><code class="language-bash">serverpod
# Should print the Serverpod CLI help
</code></pre>
<p>Make sure Docker Desktop is running before proceeding. Serverpod uses Docker to manage PostgreSQL and Redis for local development.</p>
<h2 id="heading-creating-the-project">Creating the Project</h2>
<pre><code class="language-bash">serverpod create user_profile_api
cd user_profile_api
</code></pre>
<p>This single command creates three Dart packages:</p>
<pre><code class="language-plaintext">user_profile_api/
  user_profile_api_server/    ← your server code
  user_profile_api_client/    ← auto-generated client (do not edit)
  user_profile_api_flutter/   ← Flutter app pre-configured to connect
</code></pre>
<p>For this article, everything we write lives in user_profile_api_server. The client and Flutter packages are generated automatically and used when you want a Flutter frontend talking to your Serverpod backend.</p>
<h2 id="heading-understanding-the-project-structure">Understanding the Project Structure</h2>
<p>Inside user_profile_api_server:</p>
<pre><code class="language-plaintext">user_profile_api_server/
  bin/
    main.dart                  ← entry point
  lib/
    src/
      endpoints/               ← your endpoint classes live here
      generated/               ← auto-generated code (never edit manually)
    user_profile_api_server.dart
  config/
    development.yaml           ← database and server config
    staging.yaml
    production.yaml
    passwords.yaml             ← database passwords
  migrations/                  ← auto-generated migration files
  web/                         ← optional web server files
  Dockerfile
  docker-compose.yaml
  pubspec.yaml
</code></pre>
<p>The most important thing to understand about this structure is the generated/ folder. Everything in there is produced by serverpod generate and should never be edited manually. When you change a model or endpoint, you run the generator and it rewrites that folder entirely.</p>
<p>The config/ folder holds environment-specific configuration. The development.yaml file is preconfigured to work with the Docker containers Serverpod spins up locally.</p>
<h2 id="heading-serverpod-core-concepts">Serverpod Core Concepts</h2>
<h3 id="heading-endpoints-and-the-session-object">Endpoints and the Session Object</h3>
<p>In Serverpod, an endpoint is a class that extends Endpoint. Every public method on that class becomes an API call that clients can make. There's no routing configuration, no handler registration, and no middleware mounting. The framework discovers and registers your endpoints automatically during code generation.</p>
<pre><code class="language-dart">import 'package:serverpod/serverpod.dart';

class UserEndpoint extends Endpoint {
  Future&lt;String&gt; greet(Session session, String name) async {
    return 'Hello, $name!';
  }
}
</code></pre>
<p>The Session object is the most important parameter in Serverpod. It's passed to every endpoint method and gives you access to:</p>
<ul>
<li><p>session.db for database operations</p>
</li>
<li><p>session.auth for authentication information</p>
</li>
<li><p>session.log for structured logging</p>
</li>
<li><p>session.caches for caching</p>
</li>
<li><p>session.messages for real-time messaging</p>
</li>
</ul>
<p>Think of Session as Serverpod's equivalent of Flutter's BuildContext. It's the gateway to everything the framework provides, and it's always the first parameter.</p>
<h3 id="heading-model-files-and-code-generation">Model Files and Code Generation</h3>
<p>This is where Serverpod's approach diverges most sharply from Shelf. Instead of writing Dart model classes manually, you define your data structures in .spy.yaml files and let Serverpod generate the Dart classes.</p>
<p>A model file for a Company looks like this:</p>
<pre><code class="language-yaml">class: Company
table: company
fields:
  name: String
  foundedDate: DateTime?
</code></pre>
<p>Running serverpod generate produces a full Dart class with:</p>
<ul>
<li><p>Immutable fields with correct types</p>
</li>
<li><p>toJson and fromJson for serialization</p>
</li>
<li><p>Database bindings through the db static accessor</p>
</li>
<li><p>Constructor and copyWith method</p>
</li>
<li><p>The same class is generated in the client package so the Flutter app can use it directly</p>
</li>
</ul>
<p>This is the core productivity gain. You define the shape once in YAML and get a consistent, typed model that works across the server, the database, and the client without duplication.</p>
<h3 id="heading-the-built-in-orm">The Built-in ORM</h3>
<p>Serverpod's ORM uses the generated model classes directly. All database operations go through the static db accessor on your model:</p>
<pre><code class="language-dart">// Insert a row
var company = Company(name: 'Serverpod Corp', foundedDate: DateTime.now());
company = await Company.db.insertRow(session, company);

// Find by ID
var found = await Company.db.findById(session, company.id!);

// Find with condition
var result = await Company.db.findFirstRow(
  session,
  where: (t) =&gt; t.name.equals('Serverpod Corp'),
);

// Find all with ordering
var all = await Company.db.find(
  session,
  orderBy: (t) =&gt; t.name,
);

// Update
company = company.copyWith(name: 'New Name');
await Company.db.updateRow(session, company);

// Delete
await Company.db.deleteRow(session, company);
</code></pre>
<p>The where parameter uses a type-safe expression builder. The t parameter gives you typed access to the table's columns, so you get autocompletion and compile-time checks on your query conditions. No raw SQL, no string-based column names, no runtime surprises.</p>
<h3 id="heading-migrations">Migrations</h3>
<p>When you change a model, Serverpod generates a migration automatically:</p>
<pre><code class="language-bash">serverpod create-migration
</code></pre>
<p>This creates a SQL migration file in the migrations/ directory. Apply it when starting the server:</p>
<pre><code class="language-bash">dart bin/main.dart --apply-migrations
</code></pre>
<p>Serverpod tracks which migrations have been applied and runs only the new ones. The migration system is fully integrated with the model system, so there's no drift between your Dart classes and your database schema.</p>
<h2 id="heading-starting-the-development-server">Starting the Development Server</h2>
<p>Before writing any code, get the development environment running.</p>
<p>Start the Docker containers (PostgreSQL and Redis):</p>
<pre><code class="language-bash">cd user_profile_api_server
docker compose up --build --detach
</code></pre>
<p>Start the server with migrations applied:</p>
<pre><code class="language-bash">dart bin/main.dart --apply-migrations
</code></pre>
<p>You should see:</p>
<pre><code class="language-plaintext">SERVERPOD version: 2.x.x, mode: development
Insights listening on port 8081
Server default listening on port 8080
Webserver listening on port 8082
</code></pre>
<p>Three ports: Port 8080 is the main API server. Port 8081 is the Serverpod Insights tool for monitoring. Port 8082 is an optional web server. For this article, we'll work exclusively with port 8080.</p>
<h2 id="heading-defining-the-models">Defining the Models</h2>
<h3 id="heading-the-user-model">The User Model</h3>
<p>Create lib/src/models/user.spy.yaml in the server package:</p>
<pre><code class="language-yaml">class: AppUser
table: app_users
fields:
  email: String
  passwordHash: String
  firstName: String
  lastName: String
  isActive: bool, default=true
indexes:
  app_users_email_idx:
    fields: email
    unique: true
</code></pre>
<p>A few things to note here. The class is named AppUser rather than User to avoid conflicts with Serverpod's internal User class from the auth module. The table key defines the PostgreSQL table name. The indexes block creates a unique index on the email column, enforcing uniqueness at the database level.</p>
<p>Serverpod automatically adds an id field of type int? to every model with a table key. You don't declare it yourself.</p>
<h3 id="heading-the-profile-model">The Profile Model</h3>
<p>Create lib/src/models/profile.spy.yaml:</p>
<pre><code class="language-yaml">class: Profile
table: profiles
fields:
  userId: int
  bio: String?
  avatarUrl: String?
  phone: String?
  location: String?
  website: String?
indexes:
  profiles_user_id_idx:
    fields: userId
    unique: true
</code></pre>
<p>userId is an int referencing the id of an AppUser. Serverpod's model system doesn't yet have a foreign key declaration syntax in the YAML, so referential integrity is handled at the application layer in the endpoint logic.</p>
<h3 id="heading-running-code-generation">Running Code Generation</h3>
<p>With both model files in place, run the generator:</p>
<pre><code class="language-bash">serverpod generate
</code></pre>
<p>This produces Dart classes in lib/src/generated/. For AppUser, you get:</p>
<pre><code class="language-dart">// This is auto-generated, never edit directly
class AppUser extends SerializableEntity {
  AppUser({
    this.id,
    required this.email,
    required this.passwordHash,
    required this.firstName,
    required this.lastName,
    this.isActive = true,
  });

  int? id;
  String email;
  String passwordHash;
  String firstName;
  String lastName;
  bool isActive;

  // db accessor for ORM operations
  static final db = AppUserRepository._();

  // Serialization methods
  factory AppUser.fromJson(Map&lt;String, dynamic&gt; jsonSerialization, ...) { ... }
  Map&lt;String, dynamic&gt; toJson() { ... }
}
</code></pre>
<p>The generated code is what your endpoints interact with. You never write this by hand.</p>
<h3 id="heading-creating-and-applying-migrations">Creating and Applying Migrations</h3>
<p>With the models generated, create the migration:</p>
<pre><code class="language-bash">serverpod create-migration
</code></pre>
<p>This creates timestamped SQL files in migrations/. Apply them:</p>
<pre><code class="language-bash">dart bin/main.dart --apply-migrations
</code></pre>
<p>Your app_users and profiles tables now exist in PostgreSQL with the correct columns and indexes.</p>
<h2 id="heading-building-the-api">Building the API</h2>
<h3 id="heading-the-auth-endpoint">The Auth Endpoint</h3>
<p>Create lib/src/endpoints/auth_endpoint.dart:</p>
<pre><code class="language-dart">import 'package:serverpod/serverpod.dart';
import 'package:bcrypt/bcrypt.dart';
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
import '../generated/protocol.dart';

class AuthEndpoint extends Endpoint {
  Future&lt;Map&lt;String, dynamic&gt;&gt; register(
    Session session,
    String email,
    String password,
    String firstName,
    String lastName,
  ) async {
    if (email.isEmpty || password.isEmpty || firstName.isEmpty || lastName.isEmpty) {
      throw Exception('All fields are required');
    }

    if (password.length &lt; 8) {
      throw Exception('Password must be at least 8 characters');
    }

    // Check for existing user
    final existing = await AppUser.db.findFirstRow(
      session,
      where: (t) =&gt; t.email.equals(email),
    );

    if (existing != null) {
      throw Exception('An account with this email already exists');
    }

    final passwordHash = BCrypt.hashpw(password, BCrypt.gensalt());

    var user = AppUser(
      email: email,
      passwordHash: passwordHash,
      firstName: firstName,
      lastName: lastName,
    );

    user = await AppUser.db.insertRow(session, user);

    final token = _generateToken(user);

    return {
      'user': _sanitizeUser(user),
      'token': token,
    };
  }

  Future&lt;Map&lt;String, dynamic&gt;&gt; login(
    Session session,
    String email,
    String password,
  ) async {
    if (email.isEmpty || password.isEmpty) {
      throw Exception('Email and password are required');
    }

    final user = await AppUser.db.findFirstRow(
      session,
      where: (t) =&gt; t.email.equals(email),
    );

    if (user == null || !BCrypt.checkpw(password, user.passwordHash)) {
      throw Exception('Invalid email or password');
    }

    if (!user.isActive) {
      throw Exception('This account has been deactivated');
    }

    final token = _generateToken(user);

    return {
      'user': _sanitizeUser(user),
      'token': token,
    };
  }

  String _generateToken(AppUser user) {
    final jwt = JWT({'sub': user.id, 'email': user.email});
    return jwt.sign(SecretKey(_jwtSecret), expiresIn: const Duration(hours: 24));
  }

  // Never return the password hash to the client
  Map&lt;String, dynamic&gt; _sanitizeUser(AppUser user) =&gt; {
        'id': user.id,
        'email': user.email,
        'firstName': user.firstName,
        'lastName': user.lastName,
        'isActive': user.isActive,
      };

  // Read from Serverpod's config system
  String get _jwtSecret =&gt;
      Session.serverpod.getPassword('jwtSecret') ?? 'fallback_dev_secret';
}
</code></pre>
<p>Serverpod endpoints return typed values. When you return a Map&lt;String, dynamic&gt;, Serverpod serializes it automatically. When you throw an Exception, Serverpod catches it and returns a structured error response to the client. No manual response formatting, no status code management for common cases.</p>
<h3 id="heading-the-user-endpoint">The User Endpoint</h3>
<p>Create lib/src/endpoints/user_endpoint.dart:</p>
<pre><code class="language-dart">import 'package:serverpod/serverpod.dart';
import '../generated/protocol.dart';

class UserEndpoint extends Endpoint {
  @override
  bool get requireLogin =&gt; true;

  Future&lt;List&lt;Map&lt;String, dynamic&gt;&gt;&gt; getAll(Session session) async {
    final users = await AppUser.db.find(
      session,
      where: (t) =&gt; t.isActive.equals(true),
      orderBy: (t) =&gt; t.id,
    );

    return users.map(_sanitizeUser).toList();
  }

  Future&lt;Map&lt;String, dynamic&gt;&gt; getById(Session session, int userId) async {
    final user = await AppUser.db.findById(session, userId);

    if (user == null || !user.isActive) {
      throw Exception('User not found');
    }

    return _sanitizeUser(user);
  }

  Future&lt;Map&lt;String, dynamic&gt;&gt; update(
    Session session,
    int userId,
    String? firstName,
    String? lastName,
  ) async {
    final user = await AppUser.db.findById(session, userId);

    if (user == null || !user.isActive) {
      throw Exception('User not found');
    }

    final updated = user.copyWith(
      firstName: firstName ?? user.firstName,
      lastName: lastName ?? user.lastName,
    );

    await AppUser.db.updateRow(session, updated);
    return _sanitizeUser(updated);
  }

  Future&lt;void&gt; delete(Session session, int userId) async {
    final user = await AppUser.db.findById(session, userId);

    if (user == null || !user.isActive) {
      throw Exception('User not found');
    }

    // Soft delete
    final deactivated = user.copyWith(isActive: false);
    await AppUser.db.updateRow(session, deactivated);
  }

  Map&lt;String, dynamic&gt; _sanitizeUser(AppUser user) =&gt; {
        'id': user.id,
        'email': user.email,
        'firstName': user.firstName,
        'lastName': user.lastName,
        'isActive': user.isActive,
      };
}
</code></pre>
<p>Notice @override bool get requireLogin =&gt; true. This is Serverpod's built-in mechanism for protecting endpoints. When this getter returns true, Serverpod validates the authentication token on every request to this endpoint before the method is called. Unauthenticated requests are rejected automatically by the framework.</p>
<h3 id="heading-the-profile-endpoint">The Profile Endpoint</h3>
<p>Create lib/src/endpoints/profile_endpoint.dart:</p>
<pre><code class="language-dart">import 'package:serverpod/serverpod.dart';
import '../generated/protocol.dart';

class ProfileEndpoint extends Endpoint {
  @override
  bool get requireLogin =&gt; true;

  Future&lt;Map&lt;String, dynamic&gt;&gt; getByUserId(
    Session session,
    int userId,
  ) async {
    final user = await AppUser.db.findById(session, userId);
    if (user == null || !user.isActive) {
      throw Exception('User not found');
    }

    final profile = await Profile.db.findFirstRow(
      session,
      where: (t) =&gt; t.userId.equals(userId),
    );

    if (profile == null) {
      throw Exception('Profile not found');
    }

    return _profileToMap(profile);
  }

  Future&lt;Map&lt;String, dynamic&gt;&gt; create(
    Session session,
    int userId,
    String? bio,
    String? avatarUrl,
    String? phone,
    String? location,
    String? website,
  ) async {
    final user = await AppUser.db.findById(session, userId);
    if (user == null || !user.isActive) {
      throw Exception('User not found');
    }

    final existing = await Profile.db.findFirstRow(
      session,
      where: (t) =&gt; t.userId.equals(userId),
    );

    if (existing != null) {
      throw Exception('Profile already exists for this user');
    }

    var profile = Profile(
      userId: userId,
      bio: bio,
      avatarUrl: avatarUrl,
      phone: phone,
      location: location,
      website: website,
    );

    profile = await Profile.db.insertRow(session, profile);
    return _profileToMap(profile);
  }

  Future&lt;Map&lt;String, dynamic&gt;&gt; update(
    Session session,
    int userId,
    String? bio,
    String? avatarUrl,
    String? phone,
    String? location,
    String? website,
  ) async {
    final profile = await Profile.db.findFirstRow(
      session,
      where: (t) =&gt; t.userId.equals(userId),
    );

    if (profile == null) {
      throw Exception('Profile not found');
    }

    final updated = profile.copyWith(
      bio: bio ?? profile.bio,
      avatarUrl: avatarUrl ?? profile.avatarUrl,
      phone: phone ?? profile.phone,
      location: location ?? profile.location,
      website: website ?? profile.website,
    );

    await Profile.db.updateRow(session, updated);
    return _profileToMap(updated);
  }

  Map&lt;String, dynamic&gt; _profileToMap(Profile profile) =&gt; {
        'id': profile.id,
        'userId': profile.userId,
        'bio': profile.bio,
        'avatarUrl': profile.avatarUrl,
        'phone': profile.phone,
        'location': profile.location,
        'website': profile.website,
      };
}
</code></pre>
<p>After adding these endpoints, run the generator again so Serverpod registers them:</p>
<pre><code class="language-bash">serverpod generate
</code></pre>
<h2 id="heading-authentication">Authentication</h2>
<h3 id="heading-password-hashing-and-jwt">Password Hashing and JWT</h3>
<p>Add the required packages to pubspec.yaml in the server package:</p>
<pre><code class="language-yaml">dependencies:
  serverpod: ^2.5.0
  bcrypt: ^1.1.3
  dart_jsonwebtoken: ^2.12.0
</code></pre>
<p>Then run dart pub get.</p>
<p>The _generateToken and _sanitizeUser helpers in the auth endpoint handle password hashing and JWT generation. The JWT secret is read from Serverpod's built-in password management system via Session.serverpod.getPassword('jwtSecret').</p>
<p>Add the secret to config/passwords.yaml:</p>
<pre><code class="language-yaml">development:
  database: 'dart_password'
  jwtSecret: 'your_development_jwt_secret_here'
</code></pre>
<p>This file is already in .gitignore by default in a Serverpod project. Production secrets are injected via environment variables or Serverpod Cloud's secret management.</p>
<h3 id="heading-protecting-endpoints">Protecting Endpoints</h3>
<p>Serverpod has two levels of endpoint protection:</p>
<p>requireLogin — rejects unauthenticated requests automatically:</p>
<pre><code class="language-dart">@override
bool get requireLogin =&gt; true;
</code></pre>
<p>requiredScopes — requires specific permission scopes:</p>
<pre><code class="language-dart">@override
Set&lt;Scope&gt; get requiredScopes =&gt; {Scope.admin};
</code></pre>
<p>For the User and Profile endpoints in this article, requireLogin is sufficient. The token from the login response is passed in the Authorization header on every subsequent request, and Serverpod validates it before the endpoint method is called.</p>
<p>Verifying the token inside an endpoint to get the current user's ID:</p>
<pre><code class="language-dart">Future&lt;void&gt; someProtectedMethod(Session session) async {
  final authInfo = await session.authenticated;

  if (authInfo == null) {
    throw Exception('Not authenticated');
  }

  final userId = authInfo.userId;
  // proceed with userId
}
</code></pre>
<h2 id="heading-error-handling-in-serverpod">Error Handling in Serverpod</h2>
<p>Serverpod handles exceptions thrown from endpoint methods and converts them into structured error responses automatically. When you throw:</p>
<pre><code class="language-dart">throw Exception('User not found');
</code></pre>
<p>The client receives a structured error response. For more granular control, Serverpod provides typed exceptions:</p>
<pre><code class="language-dart">throw ServerpodClientException('User not found', statusCode: 404);
</code></pre>
<p>For server-side logging without exposing details to the client:</p>
<pre><code class="language-dart">session.log('Unexpected error during user creation', level: LogLevel.error);
throw Exception('An internal error occurred');
</code></pre>
<p>Serverpod's logging system stores logs in the database and makes them queryable through the Insights dashboard on port 8081. Every request is automatically logged with timing information, endpoint name, and outcome, no additional middleware required.</p>
<h2 id="heading-testing-the-api">Testing the API</h2>
<p>Serverpod exposes its endpoints over HTTP. You can test them directly with curl, though the request format follows Serverpod's RPC convention rather than a traditional REST structure.</p>
<p>The generated URL pattern for an endpoint method is:</p>
<pre><code class="language-plaintext">POST /[endpoint]/[method]
</code></pre>
<p>With a JSON body containing the method parameters.</p>
<p>Register a user:</p>
<pre><code class="language-bash">curl http://localhost:8080/auth/register \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "email": "seyi@example.com",
    "password": "securepassword",
    "firstName": "Seyi",
    "lastName": "Dev"
  }'
</code></pre>
<p>Login:</p>
<pre><code class="language-bash">curl http://localhost:8080/auth/login \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{"email": "seyi@example.com", "password": "securepassword"}'
</code></pre>
<p>Get all users (authenticated):</p>
<pre><code class="language-bash">curl http://localhost:8080/user/getAll \
  -X POST \
  -H "Authorization: Bearer eyJhbGci..."
</code></pre>
<p>Get user by ID:</p>
<pre><code class="language-bash">curl http://localhost:8080/user/getById \
  -X POST \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -d '{"userId": 1}'
</code></pre>
<p>Create a profile:</p>
<pre><code class="language-bash">curl http://localhost:8080/profile/create \
  -X POST \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -d '{
    "userId": 1,
    "bio": "Flutter engineer turned backend developer",
    "location": "Lagos, Nigeria",
    "website": "https://example.com"
  }'
</code></pre>
<p>Update a user:</p>
<pre><code class="language-bash">curl http://localhost:8080/user/update \
  -X POST \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -d '{"userId": 1, "firstName": "Oluwaseyi"}'
</code></pre>
<p>Delete a user:</p>
<pre><code class="language-bash">curl http://localhost:8080/user/delete \
  -X POST \
  -H "Authorization: Bearer eyJhbGci..." \
  -H "Content-Type: application/json" \
  -d '{"userId": 1}'
</code></pre>
<h2 id="heading-deployment">Deployment</h2>
<h3 id="heading-deploying-with-docker-and-flyio">Deploying with Docker and Fly.io</h3>
<p>Serverpod generates a Dockerfile as part of the project creation. It's located in user_profile_api_server/Dockerfile and is ready to use.</p>
<p>The included docker-compose.yaml in the server package manages PostgreSQL and Redis for local development. For production deployment on Fly.io, the process follows the same Docker-based pattern covered in the deployment section below.</p>
<p><strong>Step 1 — Authenticate with Fly:</strong></p>
<pre><code class="language-bash">fly auth login
</code></pre>
<p><strong>Step 2 — Launch the app from the server directory:</strong></p>
<pre><code class="language-bash">cd user_profile_api_server
fly launch
</code></pre>
<p><strong>Step 3 — Set production secrets:</strong></p>
<pre><code class="language-bash">fly secrets set JWT_SECRET="your_production_jwt_secret"
</code></pre>
<p><strong>Step 4 — Update the production config:</strong></p>
<p>Edit config/production.yaml with your Fly-provisioned database connection details. Fly injects the DATABASE_URL environment variable which you map to the Serverpod config format.</p>
<p><strong>Step 5 — Deploy:</strong></p>
<pre><code class="language-bash">fly deploy
</code></pre>
<p><strong>Step 6 — Apply migrations on first deploy:</strong></p>
<pre><code class="language-bash">fly ssh console
dart bin/main.dart --apply-migrations --mode production
</code></pre>
<h3 id="heading-deploying-with-serverpod-cloud">Deploying with Serverpod Cloud</h3>
<p>Serverpod Cloud is the native deployment platform built specifically for Serverpod applications. It handles database provisioning, scaling, monitoring, and deployments with minimal configuration.</p>
<p>Install the Serverpod Cloud CLI:</p>
<pre><code class="language-bash">dart pub global activate serverpod_cloud_cli
</code></pre>
<p>Authenticate:</p>
<pre><code class="language-bash">scloud login
</code></pre>
<p>Create a project in the Serverpod Cloud dashboard at cloud.serverpod.dev, then link your local project:</p>
<pre><code class="language-bash">scloud link --project-id your-project-id
</code></pre>
<p>Deploy:</p>
<pre><code class="language-bash">scloud deploy
</code></pre>
<p>Serverpod Cloud provisions a managed PostgreSQL database, applies your migrations, and deploys your server automatically. It also provides the Insights dashboard for monitoring requests, logs, and performance in production.</p>
<p>For teams already committed to the Serverpod ecosystem, Serverpod Cloud is the fastest path to a production deployment.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Serverpod takes a fundamentally different approach from Shelf. Where Shelf gives you control, Serverpod gives you speed. You define your models in YAML, run a generator, and get database classes, serialization, and client code produced automatically. You write an endpoint method and the framework handles routing, parameter extraction, authentication, and error formatting.</p>
<p>The ORM is the strongest part of the experience. Type-safe query expressions, automatic migration generation, and no SQL drift between your code and your schema make database work noticeably faster and safer than raw SQL.</p>
<p>The cost is rigidity. Serverpod's URL structure, serialization format, and architectural conventions aren't optional. If your API needs to conform to a specific REST structure that differs from Serverpod's RPC style, you'll be working against the framework.</p>
<p>For greenfield Flutter backends where the Dart client will consume the API, Serverpod is hard to beat. The code sharing between server and client, the automatic client generation, and the tight toolchain integration make it the most productive Dart backend option available.</p>
<p>For APIs that need to serve multiple clients, conform to external REST conventions, or integrate with existing infrastructure that doesn't expect Serverpod's format, a lower-level tool like Shelf gives you more control. If you want to see how the same User and Profile Management API is built with Shelf and compare the two approaches directly, you can <a href="https://www.freecodecamp.org/news/how-to-build-and-ship-production-rest-apis-with-dart-and-shelf">find that article here</a>.</p>
<p>Knowing which tool fits which job is what separates a developer who knows a framework from one who understands backend development.</p>
<p>Happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use PostgreSQL as a Cache, Queue, and Search Engine ]]>
                </title>
                <description>
                    <![CDATA[ "Just use Postgres" has been circulating as advice for years, but most articles arguing for it are opinion pieces. I wanted hard numbers. So I built a benchmark suite that pits vanilla PostgreSQL agai ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-postgresql-as-a-cache-queue-and-search-engine/</link>
                <guid isPermaLink="false">69e7accfe43672781470ff97</guid>
                
                    <category>
                        <![CDATA[ PostgreSQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ database ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Databases ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Aaron Yong ]]>
                </dc:creator>
                <pubDate>Tue, 21 Apr 2026 16:58:55 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/6fcdd3c0-eead-42a7-b2f0-cf4c6a3d06dc.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>"Just use Postgres" has been circulating as advice for years, but most articles arguing for it are opinion pieces. I wanted hard numbers.</p>
<p>So I built a benchmark suite that pits vanilla PostgreSQL against a feature-optimized PostgreSQL instance — measuring caching, message queues, full-text search, and pub/sub under controlled conditions.</p>
<p>In this article, you'll learn how to use PostgreSQL's built-in features for caching, job queues, full-text search, and pub/sub. You'll see actual benchmark results (latency percentiles, throughput, and error rates) comparing naive PostgreSQL patterns against optimized ones, and understand where PostgreSQL's limits are so you can decide whether you really need that extra service in your stack.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-the-setup">The Setup</a></p>
</li>
<li><p><a href="#heading-benchmark-1-caching-with-unlogged-tables">Benchmark 1: Caching with UNLOGGED Tables</a></p>
</li>
<li><p><a href="#heading-benchmark-2-job-queues-with-skip-locked">Benchmark 2: Job Queues with SKIP LOCKED</a></p>
</li>
<li><p><a href="#heading-benchmark-3-full-text-search-with-tsvector">Benchmark 3: Full-Text Search with tsvector</a></p>
</li>
<li><p><a href="#heading-benchmark-4-pubsub-with-listennotify">Benchmark 4: Pub/Sub with LISTEN/NOTIFY</a></p>
</li>
<li><p><a href="#heading-the-combined-workload-the-honest-test">The Combined Workload: The Honest Test</a></p>
</li>
<li><p><a href="#heading-what-i-learned">What I Learned</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along or reproduce the benchmarks, you'll need:</p>
<ul>
<li><p>Docker and Docker Compose</p>
</li>
<li><p>Node.js 20+ (for the Express TypeScript API layer)</p>
</li>
<li><p><a href="https://k6.io/">k6</a> for load testing</p>
</li>
<li><p>Basic familiarity with SQL and PostgreSQL</p>
</li>
</ul>
<p>The full benchmark project is <a href="https://github.com/aaronhsyong2/pg-stack-benchmark">open source on GitHub</a> — you can clone it and run every test yourself.</p>
<h2 id="heading-the-setup">The Setup</h2>
<p>The benchmark uses two identical PostgreSQL 17 instances running in Docker containers, each with fixed resource constraints (2 CPUs, 2 GB RAM). Both share the same Express TypeScript API layer — the only difference is which PostgreSQL features are enabled.</p>
<pre><code class="language-plaintext">┌─────────┐     ┌──────────────────┐     ┌─────────────────┐
│   k6    │────&gt;│  Express API     │────&gt;│  PG Baseline    │
│  (load  │     │  (TypeScript)    │     │  (vanilla PG17) │
│  test)  │────&gt;│  Port 3001/3002  │────&gt;│  PG Modded      │
└─────────┘     └──────────────────┘     │  (features on)  │
                                         └─────────────────┘
</code></pre>
<p>The baseline instance uses naïve approaches (regular tables, <code>ILIKE</code> search, polling). The modded instance uses PostgreSQL's built-in features (UNLOGGED tables, <code>tsvector</code> with GIN indexes, <code>LISTEN/NOTIFY</code>, partial indexes). Same hardware, same API code, same data. Only the database features differ.</p>
<p>Both instances share this tuned <code>postgresql.conf</code>:</p>
<pre><code class="language-ini"># Memory allocation
shared_buffers = 512MB           # 25% of available RAM
effective_cache_size = 1536MB    # 75% of RAM — helps the query planner
work_mem = 16MB                  # per-sort/hash operation memory

# SSD-optimized planner settings
random_page_cost = 1.1           # default 4.0 assumes spinning disks
effective_io_concurrency = 200   # allow parallel I/O on SSDs
</code></pre>
<p>These settings matter. The defaults assume spinning disks from the early 2000s. Setting <code>random_page_cost = 1.1</code> tells the query planner that random reads are nearly as fast as sequential reads on SSDs, which encourages index usage over sequential scans.</p>
<h2 id="heading-benchmark-1-caching-with-unlogged-tables">Benchmark 1: Caching with UNLOGGED Tables</h2>
<p><strong>The idea:</strong> Use an UNLOGGED table as an in-database cache. UNLOGGED tables skip PostgreSQL's Write-Ahead Log (WAL) — the mechanism that guarantees durability. Since cache data is ephemeral by nature, losing it on a crash is acceptable, and skipping WAL removes the biggest write bottleneck.</p>
<pre><code class="language-sql">-- Modded: UNLOGGED table for cache entries
CREATE UNLOGGED TABLE cache_entries (
    key TEXT PRIMARY KEY,
    value JSONB NOT NULL,
    expires_at TIMESTAMPTZ
);

-- Baseline: same schema, but a regular (logged) table
CREATE TABLE cache_entries (
    key TEXT PRIMARY KEY,
    value JSONB NOT NULL,
    expires_at TIMESTAMPTZ
);
</code></pre>
<h3 id="heading-results-200-virtual-users">Results (200 Virtual Users)</h3>
<table>
<thead>
<tr>
<th>Mode</th>
<th>p50</th>
<th>p95</th>
<th>avg</th>
<th>req/s</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline (regular table)</td>
<td>1.87ms</td>
<td>6.00ms</td>
<td>2.50ms</td>
<td>1,754/s</td>
</tr>
<tr>
<td>Modded (UNLOGGED table)</td>
<td>1.71ms</td>
<td>5.24ms</td>
<td>2.17ms</td>
<td>1,760/s</td>
</tr>
</tbody></table>
<p>A consistent 13% improvement across all percentiles. Not dramatic, but free — you change one keyword in your <code>CREATE TABLE</code> statement.</p>
<h3 id="heading-under-stress-1000-virtual-users-no-sleep">Under Stress (1,000 Virtual Users, No Sleep)</h3>
<table>
<thead>
<tr>
<th>Mode</th>
<th>p50</th>
<th>p95</th>
<th>req/s</th>
<th>Total Requests</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline</td>
<td>83.38ms</td>
<td>143.23ms</td>
<td>7,663/s</td>
<td>728,021</td>
</tr>
<tr>
<td>Modded</td>
<td>77.69ms</td>
<td>126.39ms</td>
<td>8,062/s</td>
<td>765,934</td>
</tr>
</tbody></table>
<p>The relative improvement stays locked at 12-13% regardless of load level. The UNLOGGED advantage is a per-write optimization — it saves the same amount of I/O whether you are doing 100 or 10,000 writes per second. The modded instance served 37,000 more requests in the same time window.</p>
<h3 id="heading-the-verdict">The Verdict</h3>
<p>UNLOGGED tables won't match Redis for sub-millisecond hot-path caching (real-time bidding, gaming leaderboards). But for web applications where the difference between 2ms and 5ms is invisible to users, they eliminate an entire infrastructure dependency for zero additional complexity.</p>
<p>You do give up Redis data structures (sorted sets, HyperLogLog, streams). If you need those, a dedicated cache is still the right call.</p>
<h2 id="heading-benchmark-2-job-queues-with-skip-locked">Benchmark 2: Job Queues with SKIP LOCKED</h2>
<p><strong>The idea:</strong> Use PostgreSQL as a job queue with <code>SELECT ... FOR UPDATE SKIP LOCKED</code>. Multiple workers poll the same table, and <code>SKIP LOCKED</code> ensures each worker gets a different row — no duplicates, no contention.</p>
<pre><code class="language-sql">-- Queue table with a partial index on pending jobs only
CREATE TABLE job_queue (
    id SERIAL PRIMARY KEY,
    payload JSONB NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Partial index: only indexes pending jobs
-- As jobs complete, they leave the index — it stays small forever
CREATE INDEX idx_pending_jobs ON job_queue (created_at)
    WHERE status = 'pending';
</code></pre>
<p>The dequeue pattern:</p>
<pre><code class="language-sql">-- Atomic dequeue: select + update in one statement
UPDATE job_queue SET status = 'processing'
WHERE id = (
    SELECT id FROM job_queue
    WHERE status = 'pending'
    ORDER BY created_at
    LIMIT 1
    FOR UPDATE SKIP LOCKED  -- skip rows locked by other workers
) RETURNING *;
</code></pre>
<p>How <code>SKIP LOCKED</code> works: Worker A locks row 1. Worker B tries row 1, sees the lock, skips it, and takes row 2 instead. No blocking, no duplicates. If a worker crashes, the transaction rolls back and the row becomes available again.</p>
<h3 id="heading-results-100-producers-50-consumers">Results (100 Producers + 50 Consumers)</h3>
<table>
<thead>
<tr>
<th>Mode</th>
<th>p50</th>
<th>p95</th>
<th>avg</th>
<th>req/s</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline (full index)</td>
<td>1.90ms</td>
<td>5.01ms</td>
<td>2.30ms</td>
<td>1,053/s</td>
</tr>
<tr>
<td>Modded (partial index)</td>
<td>1.81ms</td>
<td>5.28ms</td>
<td>2.29ms</td>
<td>1,052/s</td>
</tr>
</tbody></table>
<p>They're virtually identical. The partial index doesn't show its value in a 60-second benchmark because the table doesn't accumulate enough completed rows for the index size difference to matter. In a production system with millions of completed jobs, the partial index keeps the index at kilobytes while a full index grows to gigabytes.</p>
<h3 id="heading-the-verdict">The Verdict</h3>
<p><code>SKIP LOCKED</code> is production-ready for job queues. Libraries like <a href="https://github.com/timgit/pg-boss">pg-boss</a> (Node.js) and <a href="https://github.com/riverqueue/river">river</a> (Go) build on this exact pattern.</p>
<p>You do give up exchange/routing patterns (fan-out, topic-based routing) and consumer groups with message replay. If you need those, a dedicated message broker is still the right tool. For simple "process this job once" workloads, PostgreSQL handles it.</p>
<h2 id="heading-benchmark-3-full-text-search-with-tsvector">Benchmark 3: Full-Text Search with tsvector</h2>
<p><strong>The idea:</strong> Use PostgreSQL's built-in full-text search instead of a separate search service. A <code>tsvector</code> column stores pre-processed search tokens, and a GIN (Generalized Inverted Index) enables fast lookups using the same inverted index concept that powers Elasticsearch.</p>
<pre><code class="language-sql">-- Search-optimized article table
CREATE TABLE articles (
    id SERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    body TEXT NOT NULL,
    search_vector tsvector  -- pre-computed search tokens
);

-- GIN index for full-text search
CREATE INDEX idx_search ON articles USING GIN (search_vector);

-- Auto-update search_vector on insert/update
CREATE OR REPLACE FUNCTION update_search_vector() RETURNS trigger AS $$
BEGIN
    NEW.search_vector := to_tsvector('english',
        COALESCE(NEW.title, '') || ' ' || COALESCE(NEW.body, ''));
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_search
    BEFORE INSERT OR UPDATE ON articles
    FOR EACH ROW EXECUTE FUNCTION update_search_vector();
</code></pre>
<p>The baseline uses <code>ILIKE</code> with a leading wildcard — the approach most developers reach for first:</p>
<pre><code class="language-sql">-- Baseline: sequential scan on every query
SELECT * FROM articles
WHERE title ILIKE '%postgresql%' OR body ILIKE '%postgresql%';

-- Modded: GIN index lookup with relevance ranking
SELECT id, title,
    ts_rank(search_vector, plainto_tsquery('english', 'postgresql')) AS rank
FROM articles
WHERE search_vector @@ plainto_tsquery('english', 'postgresql')
ORDER BY rank DESC LIMIT 20;
</code></pre>
<h3 id="heading-results-500-virtual-users">Results (500 Virtual Users)</h3>
<table>
<thead>
<tr>
<th>Mode</th>
<th>p50</th>
<th>p95</th>
<th>avg</th>
<th>req/s</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline (ILIKE)</td>
<td>1.96ms</td>
<td>101.83ms</td>
<td>25.22ms</td>
<td>561/s</td>
</tr>
<tr>
<td>Modded (tsvector + GIN)</td>
<td>2.76ms</td>
<td>10.39ms</td>
<td>3.76ms</td>
<td>675/s</td>
</tr>
</tbody></table>
<p>This is the standout result. The baseline's p95 of 101ms versus the modded's 10ms is a 10x improvement.</p>
<p>Why the baseline's p50 (1.96ms) is slightly better than the modded's (2.76ms): simple <code>ILIKE</code> queries on small result sets can be fast when the data fits in <code>shared_buffers</code>. But as load increases and the buffer cache is contested, sequential scans degrade dramatically. The GIN index stays stable.</p>
<h3 id="heading-under-stress-500-virtual-users-no-sleep">Under Stress (500 Virtual Users, No Sleep)</h3>
<table>
<thead>
<tr>
<th>Mode</th>
<th>p50</th>
<th>p95</th>
<th>req/s</th>
<th>Total Requests</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline (ILIKE)</td>
<td>599ms</td>
<td>1,000ms</td>
<td>558/s</td>
<td>50,212</td>
</tr>
<tr>
<td>Modded (tsvector)</td>
<td>209ms</td>
<td>396ms</td>
<td>1,441/s</td>
<td>129,679</td>
</tr>
</tbody></table>
<p>ILIKE collapses to 1-second p95 latencies. Each query forces a sequential scan of all 10,000 articles, blocking shared buffers and starving concurrent queries. The tsvector approach serves 2.6x more requests in the same time window because the GIN index lookup is O(log n) regardless of concurrency.</p>
<h3 id="heading-the-verdict">The Verdict</h3>
<p>This is the strongest argument in the entire benchmark. The fix requires zero extensions — <code>to_tsvector()</code>, <code>plainto_tsquery()</code>, and <code>CREATE INDEX USING GIN</code> are all built into core PostgreSQL. If you're doing <code>WHERE column ILIKE '%term%'</code> on any table with more than a few thousand rows, you're leaving massive performance on the table.</p>
<p>You do give up distributed search across shards, complex analyzers for CJK languages, and aggregation/faceted search pipelines. For a product search bar, blog search, or internal tool — PostgreSQL is enough.</p>
<h2 id="heading-benchmark-4-pubsub-with-listennotify">Benchmark 4: Pub/Sub with LISTEN/NOTIFY</h2>
<p><strong>The idea:</strong> Use PostgreSQL's native <code>LISTEN/NOTIFY</code> for pub/sub messaging, triggered automatically on INSERT via a database trigger.</p>
<pre><code class="language-sql">-- Trigger that fires pg_notify on every new message
CREATE OR REPLACE FUNCTION notify_message() RETURNS trigger AS $$
BEGIN
    PERFORM pg_notify(NEW.channel, NEW.payload::text);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_notify
    AFTER INSERT ON messages
    FOR EACH ROW EXECUTE FUNCTION notify_message();
</code></pre>
<h3 id="heading-results-200-virtual-users">Results (200 Virtual Users)</h3>
<table>
<thead>
<tr>
<th>Mode</th>
<th>p50</th>
<th>p95</th>
<th>avg</th>
<th>req/s</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline (poll-based)</td>
<td>1.99ms</td>
<td>6.04ms</td>
<td>2.84ms</td>
<td>1,116/s</td>
</tr>
<tr>
<td>Modded (LISTEN/NOTIFY)</td>
<td>1.65ms</td>
<td>4.80ms</td>
<td>2.13ms</td>
<td>1,131/s</td>
</tr>
</tbody></table>
<p>Here we have a 20% improvement at p95. The trigger-based approach does more work per INSERT (INSERT + NOTIFY), but the reduced round trips and better connection reuse patterns offset the overhead.</p>
<h3 id="heading-the-verdict">The Verdict</h3>
<p><code>LISTEN/NOTIFY</code> works for real-time features where you would otherwise reach for Redis pub/sub. The main limitation is payload size (8,000 bytes maximum) and the requirement for dedicated connections (incompatible with PgBouncer in transaction mode).</p>
<h2 id="heading-the-combined-workload-the-honest-test">The Combined Workload: The Honest Test</h2>
<p>Individual benchmarks are flattering. The real question: can one PostgreSQL instance handle caching, queues, search, and pub/sub simultaneously without degrading?</p>
<h3 id="heading-results-all-four-workloads-running-together">Results (All Four Workloads Running Together)</h3>
<table>
<thead>
<tr>
<th>Mode</th>
<th>p50</th>
<th>p95</th>
<th>avg</th>
<th>req/s</th>
</tr>
</thead>
<tbody><tr>
<td>Baseline</td>
<td>1.65ms</td>
<td>5.24ms</td>
<td>2.17ms</td>
<td>1,424/s</td>
</tr>
<tr>
<td>Modded</td>
<td>1.86ms</td>
<td>6.05ms</td>
<td>2.47ms</td>
<td>1,417/s</td>
</tr>
</tbody></table>
<p>Under combined load, the baseline marginally outperforms the modded setup. The modded PostgreSQL does more work per operation — maintaining GIN indexes, firing triggers, running <code>pg_cron</code> in the background. When all these features are active simultaneously, the overhead is measurable: about 15% higher p95 latency.</p>
<p>But both setups stay comfortably under 10ms at p95. For most web applications, that's more than good enough.</p>
<h2 id="heading-what-i-learned">What I Learned</h2>
<p>After running all these benchmarks, here's what I would tell a team evaluating whether to "just use Postgres":</p>
<ol>
<li><p><strong>Do it for full-text search:</strong> Switching from <code>ILIKE</code> to <code>tsvector</code> with a GIN index is a 10x improvement that requires zero extensions. This is the single highest-ROI change in the entire PostgreSQL ecosystem, and most developers don't know it exists.</p>
</li>
<li><p><strong>Do it for job queues:</strong> <code>SKIP LOCKED</code> is production-ready and eliminates RabbitMQ for simple "process this job" workloads. Use a library like pg-boss or river rather than rolling your own.</p>
</li>
<li><p><strong>Consider it for caching:</strong> UNLOGGED tables give a steady 13% improvement over regular tables. If sub-millisecond latency is not a hard requirement (and for most web apps, it is not), you can drop Redis entirely.</p>
</li>
<li><p><strong>Be honest about the overhead:</strong> Running all four roles simultaneously adds about 15% latency compared to running any single role. Whether that matters depends on your latency budget.</p>
</li>
<li><p><strong>Know where to stop:</strong> PostgreSQL won't match Redis for sub-millisecond caching, Kafka for millions of messages per second, or Elasticsearch for distributed multi-node search with complex analyzers. The line is at extreme throughput or extreme specialization.</p>
</li>
</ol>
<p>The honest conclusion is not "PostgreSQL does everything." It is: for most applications, a single well-configured PostgreSQL instance handles 80% of what you would otherwise need three to five additional services for. That is less infrastructure to deploy, monitor, and maintain — and fewer things to break at 3 AM.</p>
<p>Enterprise-scale applications processing millions of messages per second, serving sub-millisecond cache hits to millions of concurrent users, or running distributed search across terabytes of documents will still need specialized tools. Those tools exist for a reason, and at that scale the operational cost of running them is justified by the performance you get back.</p>
<p>But most of us aren't building at that scale — and may never need to. Starting with PostgreSQL for these roles means you ship faster with fewer moving parts. If and when you outgrow what PostgreSQL can handle, your benchmarks will tell you exactly which role needs to be extracted into a dedicated service. That is a much better position than starting with five services on day one because you assumed you would need them.</p>
<p>The <a href="https://github.com/aaronhsyong2/pg-stack-benchmark">benchmark project</a> is open source if you want to reproduce these results or adapt the tests for your own workload.</p>
<p>You can find more of my writing at <a href="https://site.aaronhsyong.com">site.aaronhsyong.com</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build Real-Time Update Systems with MQTT and Express.js  ]]>
                </title>
                <description>
                    <![CDATA[ Real-time updates are everywhere – like live sports scores, stock tickers, chat applications, and IoT dashboards. If you want to build systems that push data to users the moment it changes, you need t ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-real-time-update-systems-with-mosquitto-and-expressjs/</link>
                <guid isPermaLink="false">69b04145abc0d950017e4629</guid>
                
                    <category>
                        <![CDATA[ Express ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mqtt ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web application ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ David Aniebo ]]>
                </dc:creator>
                <pubDate>Tue, 10 Mar 2026 16:05:25 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/f39f54d7-d39b-46aa-9046-9a88315369d4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Real-time updates are everywhere – like live sports scores, stock tickers, chat applications, and IoT dashboards. If you want to build systems that push data to users the moment it changes, you need the right tools.</p>
<p>Message Queuing Telemetry Transport (MQTT) is a lightweight messaging protocol that excels at this. Combined with a broker like Mosquitto and a web framework like Express, you can build a production-ready real-time system in a single afternoon.</p>
<p>In this tutorial, you'll build a complete real-time football (soccer) sports update system from scratch. You'll create an admin interface for uploading scores and match details, a viewer interface for watching live updates, and a backend that uses MQTT to broadcast changes instantly to every connected client.</p>
<p>By the end of this guide, you'll understand how to integrate MQTT with Express, set up the Mosquitto broker, and deliver real-time data to web browsers using Server-Sent Events. You will have a working system that you can extend for production use.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a href="#heading-what-you-will-learn">What You Will Learn</a></p>
</li>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-understanding-the-architecture">Understanding the Architecture</a></p>
</li>
<li><p><a href="#heading-what-is-mqtt-and-why-use-it">What is MQTT and Why Use It?</a></p>
<ul>
<li><p><a href="#heading-mqtt-topic-design">MQTT Topic Design</a></p>
</li>
<li><p><a href="#heading-why-serversent-events-instead-of-websockets">Why Server-Sent Events Instead of WebSockets?</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-project-setup">Project Setup</a></p>
</li>
<li><p><a href="#heading-how-to-set-up-the-mqtt-broker">How to Set Up the MQTT Broker</a></p>
<ul>
<li><p><a href="#heading-option-1-docker-recommended">Option 1: Docker (Recommended)</a></p>
</li>
<li><p><a href="#heading-option-2-local-install">Option 2: Local Install</a></p>
</li>
<li><p><a href="#heading-option-3-public-test-broker">Option 3: Public Test Broker</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-build-the-express-server">How to Build the Express Server</a></p>
</li>
<li><p><a href="#heading-how-to-implement-the-match-routes">How to Implement the Match Routes</a></p>
</li>
<li><p><a href="#heading-how-to-bridge-mqtt-to-the-browser-with-serversent-events">How to Bridge MQTT to the Browser with Server-Sent Events</a></p>
</li>
<li><p><a href="#heading-how-to-build-the-admin-upload-interface">How to Build the Admin Upload Interface</a></p>
<ul>
<li><p><a href="#heading-admin-html-structure-and-styles">Admin HTML Structure and Styles</a></p>
</li>
<li><p><a href="#heading-admin-javascript-logic">Admin JavaScript Logic</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-how-to-build-the-live-viewer-interface">How to Build the Live Viewer Interface</a></p>
<ul>
<li><a href="#heading-viewer-javascript-logic">Viewer JavaScript Logic</a></li>
</ul>
</li>
<li><p><a href="#heading-how-to-build-the-home-page">How to Build the Home Page</a></p>
</li>
<li><p><a href="#heading-how-to-run-and-test-the-system">How to Run and Test the System</a></p>
</li>
<li><p><a href="#heading-how-to-extend-the-system-for-production">How to Extend the System for Production</a></p>
</li>
<li><p><a href="#heading-api-reference">API Reference</a></p>
</li>
<li><p><a href="#heading-troubleshooting">Troubleshooting</a></p>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-you-will-learn">What You Will Learn</h2>
<p>During this tutorial, you'll learn how to:</p>
<ul>
<li><p>Connect an Express server to an MQTT broker using the MQTT.js library</p>
</li>
<li><p>Publish and subscribe to MQTT topics for real-time messaging</p>
</li>
<li><p>Use Server-Sent Events to push MQTT messages to web browsers</p>
</li>
<li><p>Build a REST application programming interface (API) for match and score management</p>
</li>
<li><p>Create a simple admin interface for uploading match data</p>
</li>
<li><p>Create a viewer interface that updates in real time without page refreshes</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start, you should have:</p>
<ul>
<li><p>Node.js version 18 or later installed on your machine</p>
</li>
<li><p>Basic familiarity with JavaScript, Express, and HTML</p>
</li>
<li><p>A terminal or command line for running commands</p>
</li>
<li><p>Docker installed (optional, for running Mosquitto in a container)</p>
</li>
</ul>
<p>If you don't have Node.js installed, you can download it from the official Node.js website.</p>
<h2 id="heading-understanding-the-architecture">Understanding the Architecture</h2>
<p>The system has three main parts:</p>
<ol>
<li><p><strong>Admin interface</strong> – A web page where you create matches, update scores, and add events such as goals and cards.</p>
</li>
<li><p><strong>Express server</strong> – Receives HyperText Transfer Protocol (HTTP) requests from the admin, publishes data to MQTT, subscribes to MQTT topics, and streams updates to viewers via Server-Sent Events.</p>
</li>
<li><p><strong>Viewer interface</strong> – A web page that connects to the server and displays live scores and events as they arrive.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/6904c2dbd42ef6b1f9e61c3e/e6d0b007-764d-41bf-8d05-9e37971bd78e.png" alt="Architecture-diagram" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p><strong>How the flow works</strong><br>When you submit a score update in the admin panel, the Express server publishes a message to the MQTT broker. The server also subscribes to those same topics. When a message arrives, the server forwards it to all connected viewers through Server-Sent Events. The viewers update their display without refreshing the page.</p>
<h2 id="heading-what-is-mqtt-and-why-use-it">What is MQTT and Why Use It?</h2>
<p>MQTT stands for Message Queuing Telemetry Transport. It's a lightweight, publish-subscribe messaging protocol designed for low bandwidth and unreliable networks. It's widely used in Internet of Things (IoT) applications, but it works well for any real-time system where you need to broadcast updates to many subscribers.</p>
<p>Here are some reasons to use MQTT for a sports update system:</p>
<ul>
<li><p><strong>Low overhead</strong>: Messages are small and efficient, which helps when you have many clients.</p>
</li>
<li><p><strong>Built-in Quality of Service (QoS)</strong>: You can choose how many times a message is delivered (at most once, at least once, or exactly once).</p>
</li>
<li><p><strong>Topic-based routing</strong>: You organize messages by topic (for example, <code>sports/football/match/123</code>) so subscribers receive only what they need.</p>
</li>
<li><p><strong>Broker-based</strong>: A central broker (Mosquitto) handles all message distribution, so your application logic stays simple.</p>
</li>
</ul>
<p>Mosquitto is a popular, open-source MQTT broker that's easy to install and configure.</p>
<h3 id="heading-mqtt-topic-design">MQTT Topic Design</h3>
<p>MQTT uses a hierarchical topic structure. For this project, the topics are:</p>
<ul>
<li><p><code>sports/football/match/{id}</code>: One topic per match. When you publish the full match object here, any subscriber receives the complete state. This makes it easy to add new match fields later without changing the topic structure.</p>
</li>
<li><p><code>sports/football/scores</code>: A single topic for score-related notifications. Messages include a <code>type</code> field (<code>match_created</code> or <code>score_update</code>) so subscribers can handle them differently.</p>
</li>
<li><p><code>sports/football/events</code>: A topic for match events such as goals and cards. Subscribers receive <code>{ type: 'match_event', matchId, event }</code>.</p>
</li>
</ul>
<p>The <code>#</code> wildcard in a subscription means "match this level and all levels below." So <code>sports/football/#</code> subscribes to every topic under <code>sports/football</code>, including <code>sports/football/match/abc123</code> and <code>sports/football/scores</code>. The <code>+</code> wildcard matches exactly one level. For example, <code>sports/+/match/#</code> would match any sport, not just football.</p>
<h3 id="heading-why-server-sent-events-instead-of-websockets">Why Server-Sent Events Instead of WebSockets?</h3>
<p>You might wonder why this tutorial uses Server-Sent Events (SSE) instead of WebSockets. Both can push data to the browser. The main difference:</p>
<ul>
<li><p><strong>Server-Sent Events</strong>: One-way (server to client). Built on HTTP. Automatic reconnection in the browser. Simpler to implement. No extra libraries.</p>
</li>
<li><p><strong>WebSockets</strong>: Two-way. Requires a different protocol. More flexible but more complex.</p>
</li>
</ul>
<p>For a sports score viewer, you only need server-to-client updates. The viewer never sends messages back over the same channel. Server-Sent Events is a better fit. If you later need the client to send commands (for example, to filter by league), you can add a separate HTTP API or switch to WebSockets.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Start by creating a new folder for your project and initialize it with npm. The <code>mkdir</code> command creates the directory, <code>cd</code> moves into it, and <code>npm init -y</code> creates a <code>package.json</code> file with default values without prompting you for input.</p>
<pre><code class="language-shell">mkdir mqtt-football-scores
cd mqtt-football-scores
npm init -y
</code></pre>
<p>Install the required dependencies. Each package serves a specific role in the application. Run this command in the project root directory.</p>
<pre><code class="language-shell">npm install express cors mqtt uuid
</code></pre>
<ul>
<li><p><code>express</code>: Web framework for the HTTP server and API. It provides routing, middleware, and static file serving.</p>
</li>
<li><p><code>cors</code>: Enables Cross-Origin Resource Sharing so your frontend can call the API from a different origin (for example, if you serve the HTML from a different port or domain).</p>
</li>
<li><p><code>mqtt</code>: MQTT client for Node.js. It handles connection, publish, subscribe, reconnection, and Quality of Service (QoS) flows.</p>
</li>
<li><p><code>uuid</code>: Generates unique identifiers (Universally Unique Identifiers) for matches and events. Each ID is practically unique across all systems.</p>
</li>
</ul>
<p>Next, create the following folder structure. The <code>server</code> folder holds the Node.js backend code. The <code>public</code> folder holds the HTML, CSS, and client-side JavaScript that the browser loads. The <code>routes</code> subfolder keeps the match-related route handlers separate from the main server file.</p>
<pre><code class="language-plaintext">mqtt-football-scores/
├── server/
│   ├── index.js
│   ├── sse.js
│   └── routes/
│       └── matches.js
├── public/
│   ├── index.html
│   ├── admin.html
│   └── viewer.html
├── mosquitto.conf
├── docker-compose.yml
└── package.json
</code></pre>
<p>Add <code>"type": "module"</code> to your <code>package.json</code> so you can use JavaScript modules (import and export). The <code>type</code> field tells Node.js to treat <code>.js</code> files as ES modules, which allows you to use <code>import</code> and <code>export</code> syntax instead of CommonJS <code>require</code> and <code>module.exports</code>.</p>
<pre><code class="language-json">{
  "name": "mqtt-football-scores",
  "version": "1.0.0",
  "type": "module",
  "main": "server/index.js"
}
</code></pre>
<h2 id="heading-how-to-set-up-the-mqtt-broker">How to Set Up the MQTT Broker</h2>
<p>You need an MQTT broker running before the server can connect. You have three options.</p>
<h3 id="heading-option-1-docker-recommended">Option 1: Docker (Recommended)</h3>
<p>Create a <code>docker-compose.yml</code> file. This file defines a single service named <code>mosquitto</code> that runs the Eclipse Mosquitto 2 image. The <code>ports</code> directive maps port 1883 on your host to port 1883 in the container so your Express server can connect. The <code>volumes</code> directive mounts your local <code>mosquitto.conf</code> into the container so the broker uses your configuration. The <code>restart: unless-stopped</code> option ensures the container restarts automatically if it crashes or if you reboot your machine.</p>
<pre><code class="language-yaml">version: "3.8"

services:
  mosquitto:
    image: eclipse-mosquitto:2
    container_name: mqtt-football-mosquitto
    ports:
      - "1883:1883"
    volumes:
      - ./mosquitto.conf:/mosquitto/config/mosquitto.conf
    restart: unless-stopped
</code></pre>
<p>Create a <code>mosquitto.conf</code> file. The <code>listener 1883</code> directive tells Mosquitto to listen on port 1883 for MQTT connections. The <code>protocol mqtt</code> specifies the standard MQTT protocol (as opposed to WebSocket). The <code>allow_anonymous true</code> setting permits connections without a username and password, which is fine for local development but should be disabled in production. The <code>log_dest stdout</code> and <code>log_type all</code> directives send all log output to the console so you can debug connection issues.</p>
<pre><code class="language-plaintext">listener 1883
protocol mqtt
allow_anonymous true
log_dest stdout
log_type all
</code></pre>
<p>Start the broker:</p>
<pre><code class="language-bash">docker-compose up -d
</code></pre>
<h3 id="heading-option-2-local-install">Option 2: Local Install</h3>
<p>On macOS with Homebrew:</p>
<pre><code class="language-bash">brew install mosquitto
mosquitto -c mosquitto.conf
</code></pre>
<p>On Ubuntu or Debian:</p>
<pre><code class="language-bash">sudo apt install mosquitto mosquitto-clients
sudo systemctl start mosquitto
</code></pre>
<h3 id="heading-option-3-public-test-broker">Option 3: Public Test Broker</h3>
<p>You can use the public test broker at <code>test.mosquitto.org</code> without installing anything. Set the environment variable when you start the server:</p>
<pre><code class="language-bash">MQTT_BROKER=mqtt://test.mosquitto.org npm start
</code></pre>
<p>Note: The public broker is shared and not suitable for production. Use it only for development and testing.</p>
<h2 id="heading-how-to-build-the-express-server">How to Build the Express Server</h2>
<p>In this step, you'll create the main server that powers the real-time application. The Express server handles HTTP requests, serves static files like HTML and JavaScript, and acts as the bridge between the browser and the MQTT broker. It also provides endpoints that allow data to be sent and received in real time. Essentially, this server is the backbone of the application, enabling communication between all components.</p>
<p>Begin by creating the main server file at <code>server/index.js</code>:</p>
<pre><code class="language-typescript">import express from 'express';
import cors from 'cors';
import mqtt from 'mqtt';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { v4 as uuidv4 } from 'uuid';

import { matchRoutes } from './routes/matches.js';
import { setupSSE, addSSEClient } from './sse.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const MQTT_BROKER = process.env.MQTT_BROKER || 'mqtt://localhost:1883';
const PORT = process.env.PORT || 3000;

const app = express();
app.use(cors());
app.use(express.json());
app.use(express.static(join(__dirname, '../public')));

let mqttClient = null;

function connectMQTT() {
  mqttClient = mqtt.connect(MQTT_BROKER, {
    clientId: `football-scores-${uuidv4().slice(0, 8)}`,
    reconnectPeriod: 3000,
    connectTimeout: 10000,
  });

  mqttClient.on('connect', () =&gt; {
    console.log('Connected to MQTT broker at', MQTT_BROKER);
    mqttClient.subscribe('sports/football/#', { qos: 1 }, (err) =&gt; {
      if (err) console.error('Subscribe error:', err);
    });
  });

  mqttClient.on('error', (err) =&gt; {
    console.error('MQTT error:', err.message);
  });

  mqttClient.on('close', () =&gt; {
    console.log('MQTT connection closed');
  });

  mqttClient.on('reconnect', () =&gt; {
    console.log('MQTT reconnecting...');
  });

  return mqttClient;
}

const mqttClientInstance = connectMQTT();
const { publishMatch, publishScoreUpdate, publishEvent, getMatches } = matchRoutes(mqttClientInstance);
setupSSE(mqttClientInstance);

app.get('/api/events', (req, res) =&gt; addSSEClient(res));
app.post('/api/matches', publishMatch);
app.patch('/api/matches/:id/score', publishScoreUpdate);
app.post('/api/matches/:id/events', publishEvent);
app.get('/api/matches', getMatches);

app.listen(PORT, () =&gt; {
  console.log(`Football Scores Server running at http://localhost:${PORT}`);
  console.log(`Admin (upload):  http://localhost:${PORT}/admin.html`);
  console.log(`Viewer:          http://localhost:${PORT}/viewer.html`);
});
</code></pre>
<p>Here is what each part does:</p>
<ul>
<li><p><strong>Imports</strong>: The <code>fileURLToPath</code> and <code>dirname</code> utilities replicate the <code>__dirname</code> variable that CommonJS provides, since ES modules don't have it. You need <code>__dirname</code> to build the path to the <code>public</code> folder.</p>
</li>
<li><p><strong>Environment variables</strong>: <code>MQTT_BROKER</code> defaults to <code>mqtt://localhost:1883</code> so the server connects to a local Mosquitto instance. You can override it for Docker or a remote broker. <code>PORT</code> defaults to 3000.</p>
</li>
<li><p><strong>Middleware</strong>: <code>cors()</code> allows requests from any origin, which is useful during development. <code>express.json()</code> parses JSON request bodies. <code>express.static()</code> serves files from <code>public</code> so <code>/admin.html</code> and <code>/viewer.html</code> are available.</p>
</li>
<li><p><strong>connectMQTT</strong>: Creates an MQTT client with a unique client ID (required by the broker), a 3-second reconnect interval, and a 10-second connection timeout. On connect, it subscribes to <code>sports/football/#</code> with QoS 1. The <code>#</code> wildcard means "all topics under sports/football."</p>
</li>
<li><p><strong>matchRoutes</strong>: Returns the route handlers that create matches, update scores, and add events. Each handler publishes to MQTT and responds with JSON.</p>
</li>
<li><p><strong>setupSSE</strong>: Registers a listener on the MQTT client's <code>message</code> event. When a message arrives, it forwards the payload to all connected Server-Sent Events clients.</p>
</li>
<li><p><strong>addSSEClient</strong>: Called when a viewer opens <code>/api/events</code>. It sets the response headers for Server-Sent Events, flushes the headers so the connection stays open, and adds the response object to a set of active clients.</p>
</li>
<li><p><strong>Routes</strong>: The GET <code>/api/events</code> route establishes the Server-Sent Events stream. The POST, PATCH, and GET routes for matches delegate to the handlers from <code>matchRoutes</code>.</p>
</li>
</ul>
<p>The server serves static files from the <code>public</code> folder, so your HTML pages are available at the root.</p>
<h2 id="heading-how-to-implement-the-match-routes">How to Implement the Match Routes</h2>
<p>In this step, you'll create the route handlers that manage matches, scores, and events. These routes allow the server to receive requests from the admin interface, update match data, and publish real-time updates to MQTT. They also store match information in memory so it can be retrieved and updated during the session.</p>
<p>Begin by creating the file at <code>server/routes/matches.js</code>:</p>
<pre><code class="language-javascript">import { v4 as uuidv4 } from 'uuid';

const TOPIC_MATCH = 'sports/football/match';
const TOPIC_SCORES = 'sports/football/scores';
const TOPIC_EVENTS = 'sports/football/events';

const matches = new Map();

function publish(client, topic, payload, qos = 1) {
  if (!client?.connected) {
    console.warn('MQTT not connected, message not published');
    return false;
  }
  client.publish(topic, JSON.stringify(payload), { qos, retain: false });
  return true;
}

export function matchRoutes(mqttClient) {
  return {
    publishMatch: (req, res) =&gt; {
      const { homeTeam, awayTeam, league, venue, kickoff } = req.body;
      if (!homeTeam || !awayTeam) {
        return res.status(400).json({ error: 'homeTeam and awayTeam are required' });
      }

      const match = {
        id: uuidv4(),
        homeTeam,
        awayTeam,
        homeScore: 0,
        awayScore: 0,
        league: league || 'Premier League',
        venue: venue || 'TBD',
        kickoff: kickoff || new Date().toISOString(),
        status: 'scheduled',
        minute: 0,
        events: [],
        createdAt: new Date().toISOString(),
      };

      matches.set(match.id, match);

      const topic = `\({TOPIC_MATCH}/\){match.id}`;
      publish(mqttClient, topic, match);
      publish(mqttClient, TOPIC_SCORES, { type: 'match_created', match });

      res.status(201).json(match);
    },

    publishScoreUpdate: (req, res) =&gt; {
      const { id } = req.params;
      const { homeScore, awayScore, minute, status } = req.body;

      const match = matches.get(id);
      if (!match) {
        return res.status(404).json({ error: 'Match not found' });
      }

      if (homeScore !== undefined) match.homeScore = homeScore;
      if (awayScore !== undefined) match.awayScore = awayScore;
      if (minute !== undefined) match.minute = minute;
      if (status !== undefined) match.status = status;

      const topic = `\({TOPIC_MATCH}/\){id}`;
      publish(mqttClient, topic, match);
      publish(mqttClient, TOPIC_SCORES, {
        type: 'score_update',
        matchId: id,
        homeScore: match.homeScore,
        awayScore: match.awayScore,
        minute: match.minute,
        status: match.status,
      });

      res.json(match);
    },

    publishEvent: (req, res) =&gt; {
      const { id } = req.params;
      const { type, team, player, minute, description } = req.body;

      const match = matches.get(id);
      if (!match) {
        return res.status(404).json({ error: 'Match not found' });
      }

      const event = {
        id: uuidv4().slice(0, 8),
        type: type || 'goal',
        team,
        player: player || 'Unknown',
        minute: minute ?? match.minute,
        description: description || `\({type}: \){player}`,
        timestamp: new Date().toISOString(),
      };

      match.events.push(event);
      if (type === 'goal') {
        if (team === match.homeTeam) match.homeScore++;
        else if (team === match.awayTeam) match.awayScore++;
      }

      const topic = `\({TOPIC_MATCH}/\){id}`;
      publish(mqttClient, topic, match);
      publish(mqttClient, TOPIC_EVENTS, { type: 'match_event', matchId: id, event });

      res.status(201).json({ match, event });
    },

    getMatches: (req, res) =&gt; {
      const list = Array.from(matches.values()).sort(
        (a, b) =&gt; new Date(b.createdAt) - new Date(a.createdAt)
      );
      res.json(list);
    },
  };
}
</code></pre>
<p>The routes use an in-memory <code>Map</code> to store matches. In production, you would replace this with a database such as PostgreSQL or MongoDB.</p>
<p>Explanation of the key logic:</p>
<ul>
<li><p><strong>publish</strong>: A helper that checks if the MQTT client is connected before publishing. If the broker is down, it logs a warning instead of throwing. The <code>retain: false</code> option means the broker doesn't store the last message for new subscribers.</p>
</li>
<li><p><strong>publishMatch</strong>: Validates that <code>homeTeam</code> and <code>awayTeam</code> are present. Creates a match object with default values for league, venue, kickoff, status, and events. Stores it in the Map, publishes to the match-specific topic and the scores topic, and returns the match with status 201 (Created).</p>
</li>
<li><p><strong>publishScoreUpdate</strong>: Looks up the match by ID. If not found, returns 404. Updates only the fields that are provided (using <code>!== undefined</code> so you can set a score to 0). Publishes the full match and a score_update notification.</p>
</li>
<li><p><strong>publishEvent</strong>: Creates an event object with a short unique ID. Pushes it to the match's events array. If the event type is <code>goal</code>, increments the home or away score based on the team. Publishes the updated match and an event notification.</p>
</li>
<li><p><strong>getMatches</strong>: Converts the Map to an array, sorts by <code>createdAt</code> descending (newest first), and returns the list as JSON.</p>
</li>
</ul>
<p>MQTT topics used:</p>
<ul>
<li><p><code>sports/football/match/{id}</code>: Full match state. Used when a match is created or updated.</p>
</li>
<li><p><code>sports/football/scores</code>: Score change notifications. Used for match creation and score updates.</p>
</li>
<li><p><code>sports/football/events</code>: Match events such as goals and cards.</p>
</li>
</ul>
<p>The <code>publish</code> function sends JavaScript Object Notation (JSON) payloads with QoS 1 (at least once delivery). MQTT defines three QoS levels: 0 (at most once), 1 (at least once), and 2 (exactly once). Level 1 ensures the broker will retry until the subscriber acknowledges the message, which reduces the chance of losing score updates if the connection drops briefly.</p>
<h2 id="heading-how-to-bridge-mqtt-to-the-browser-with-server-sent-events">How to Bridge MQTT to the Browser with Server-Sent Events</h2>
<p>In this step, you'll create the Server-Sent Events (SSE) module that bridges MQTT messages to the browser. MQTT works over TCP and browsers cannot connect to it directly, so we use SSE as a lightweight HTTP-based streaming channel. SSE keeps an open connection and allows the server to push updates to connected browsers in real time. This is what enables viewers to see match updates instantly without refreshing.</p>
<p>Now create the file at <code>server/sse.js</code>:</p>
<pre><code class="language-javascript">const clients = new Set();

export function setupSSE(mqttClient) {
  if (!mqttClient) return;

  mqttClient.on('message', (topic, message) =&gt; {
    try {
      const payload = JSON.parse(message.toString());
      const data = JSON.stringify({ topic, ...payload });
      clients.forEach((res) =&gt; {
        try {
          res.write(`data: ${data}\n\n`);
        } catch (e) {
          clients.delete(res);
        }
      });
    } catch (e) {
      console.error('SSE parse error:', e.message);
    }
  });
}

export function addSSEClient(res) {
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');
  res.setHeader('X-Accel-Buffering', 'no');
  res.flushHeaders();

  clients.add(res);

  res.on('close', () =&gt; {
    clients.delete(res);
  });
}
</code></pre>
<p>Explanation of each part:</p>
<ul>
<li><p><strong>clients Set</strong>: A Set holds all active Server-Sent Events response objects. Using a Set makes it easy to add and remove clients without duplicates.</p>
</li>
<li><p><strong>setupSSE</strong>: Attaches a <code>message</code> listener to the MQTT client. When any message arrives on a subscribed topic, the callback runs. It parses the message payload (which is JSON), merges the topic into the payload with <code>{ topic, ...payload }</code>, and sends the result to every client. The Server-Sent Events format requires each message to be <code>data: {content}\n\n</code> (two newlines). The <code>forEach</code> loop catches write errors (for example, if a client disconnected) and removes the client from the set.</p>
</li>
<li><p><strong>addSSEClient</strong>: Sets the <code>Content-Type</code> header to <code>text/event-stream</code> so the browser treats the response as an event stream. The <code>Cache-Control: no-cache</code> and <code>Connection: keep-alive</code> headers prevent the browser or proxy from caching or closing the connection. The <code>X-Accel-Buffering: no</code> header disables buffering in Nginx, which can delay or block Server-Sent Events. The <code>flushHeaders</code> call sends the headers immediately so the connection is established. The <code>close</code> event handler removes the client when the client disconnects (closes the tab or navigates away).</p>
</li>
</ul>
<p>Server-Sent Events is one-way (server to client). For this use case, that is enough because viewers only need to receive updates, not send messages back over the same channel.</p>
<h2 id="heading-how-to-build-the-admin-upload-interface">How to Build the Admin Upload Interface</h2>
<p>The admin interface is a single HTML page where match creators can create new matches, update scores, and add events such as goals or cards. It uses standard HTML forms so data can be submitted to the server, and JavaScript will later handle form submissions and dynamic updates. All the markup, styles, and script live in <code>public/admin.html</code>, which the Express server serves as a static page.</p>
<h3 id="heading-admin-html-structure-and-styles">Admin HTML Structure and Styles</h3>
<p>The document starts with the standard HTML5 boilerplate. The <code>charset</code> and <code>viewport</code> meta tags ensure proper character encoding and responsive layout on mobile devices. The page loads the Outfit font from Google Fonts for a clean, modern look.</p>
<p>The Cascading Style Sheets (CSS) uses custom properties (variables) in the <code>:root</code> block so you can change the color scheme in one place. The <code>--bg</code> variable holds the dark background color, <code>--surface</code> for card backgrounds, <code>--accent</code> for the green accent color, and <code>--text-muted</code> for secondary text. The <code>.grid</code> class creates a two-column layout for form fields that collapses to one column on screens under 600 pixels wide. The <code>.toast</code> class positions the notification at the bottom-right and uses <code>transform</code> and <code>opacity</code> for a slide-in animation when the <code>.show</code> class is added.</p>
<p>Now create the file at <code>public/admin.html</code>:</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;title&gt;Admin - Football Scores Upload&lt;/title&gt;
  &lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
  &lt;link rel="preconnect" href="https://fonts.gstatic.com" crossorigin&gt;
  &lt;link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
  &lt;style&gt;
    :root {
      --bg: #0f1419;
      --surface: #1a2332;
      --surface-hover: #243044;
      --accent: #00d26a;
      --accent-dim: #00a854;
      --text: #e8edf2;
      --text-muted: #8b9aab;
      --border: #2d3a4d;
      --danger: #ff4757;
    }
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: 'Outfit', sans-serif;
      background: var(--bg);
      color: var(--text);
      min-height: 100vh;
      padding: 2rem;
    }
    .container { max-width: 900px; margin: 0 auto; }
    header {
      display: flex;
      align-items: center;
      gap: 1rem;
      margin-bottom: 2rem;
      padding-bottom: 1rem;
      border-bottom: 1px solid var(--border);
    }
    section {
      background: var(--surface);
      border-radius: 12px;
      padding: 1.5rem;
      margin-bottom: 1.5rem;
      border: 1px solid var(--border);
    }
    .grid {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 1rem;
    }
    @media (max-width: 600px) { .grid { grid-template-columns: 1fr; } }
    .form-group { display: flex; flex-direction: column; gap: 0.4rem; }
    .form-group.full { grid-column: 1 / -1; }
    input, select {
      padding: 0.65rem 1rem;
      border: 1px solid var(--border);
      border-radius: 8px;
      background: var(--bg);
      color: var(--text);
      font-family: inherit;
    }
    button {
      padding: 0.75rem 1.5rem;
      border: none;
      border-radius: 8px;
      font-family: inherit;
      font-weight: 600;
      cursor: pointer;
    }
    .btn-primary { background: var(--accent); color: var(--bg); }
    .btn-secondary { background: var(--surface-hover); color: var(--text); border: 1px solid var(--border); }
    .actions { display: flex; gap: 0.75rem; flex-wrap: wrap; margin-top: 1rem; }
    .badge { background: var(--accent); color: var(--bg); font-size: 0.75rem; padding: 0.25rem 0.6rem; border-radius: 999px; font-weight: 600; }
    .viewer-link { margin-left: auto; color: var(--accent); text-decoration: none; font-weight: 500; }
    section h2 { font-size: 1rem; font-weight: 600; margin-bottom: 1rem; color: var(--text-muted); }
    label { font-size: 0.85rem; font-weight: 500; color: var(--text-muted); }
    .toast {
      position: fixed;
      bottom: 2rem;
      right: 2rem;
      padding: 1rem 1.5rem;
      border-radius: 8px;
      font-weight: 500;
      color: var(--bg);
      background: var(--accent);
      transform: translateY(100px);
      opacity: 0;
      transition: transform 0.3s, opacity 0.3s;
      z-index: 100;
    }
    .toast.show { transform: translateY(0); opacity: 1; }
    .toast.error { background: var(--danger); }
    .match-card {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 1rem;
      background: var(--bg);
      border-radius: 8px;
      margin-bottom: 0.5rem;
      border: 1px solid var(--border);
    }
    .match-score { font-size: 1.5rem; font-weight: 700; color: var(--accent); margin: 0 1rem; }
    .match-info { flex: 1; }
    .match-teams { font-weight: 600; font-size: 1rem; }
    .match-meta { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.25rem; }
    .match-actions { display: flex; gap: 0.5rem; }
    .match-actions button { padding: 0.5rem 1rem; font-size: 0.85rem; }
    .match-list { margin-top: 1rem; }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div class="container"&gt;
    &lt;header&gt;
      &lt;h1&gt;⚽ Football Scores&lt;/h1&gt;
      &lt;span class="badge"&gt;Admin&lt;/span&gt;
      &lt;a href="/viewer.html" class="viewer-link"&gt;→ Open Viewer&lt;/a&gt;
    &lt;/header&gt;

    &lt;section&gt;
      &lt;h2&gt;Create New Match&lt;/h2&gt;
      &lt;form id="createMatch"&gt;
        &lt;div class="grid"&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="homeTeam"&gt;Home Team&lt;/label&gt;
            &lt;input type="text" id="homeTeam" placeholder="e.g. Manchester United" required&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="awayTeam"&gt;Away Team&lt;/label&gt;
            &lt;input type="text" id="awayTeam" placeholder="e.g. Liverpool" required&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="league"&gt;League&lt;/label&gt;
            &lt;input type="text" id="league" placeholder="e.g. Premier League" value="Premier League"&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="venue"&gt;Venue&lt;/label&gt;
            &lt;input type="text" id="venue" placeholder="e.g. Old Trafford"&gt;
          &lt;/div&gt;
          &lt;div class="form-group full"&gt;
            &lt;label for="kickoff"&gt;Kickoff (ISO)&lt;/label&gt;
            &lt;input type="datetime-local" id="kickoff"&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class="actions"&gt;
          &lt;button type="submit" class="btn-primary"&gt;Create Match&lt;/button&gt;
        &lt;/div&gt;
      &lt;/form&gt;
    &lt;/section&gt;

    &lt;section&gt;
      &lt;h2&gt;Update Score&lt;/h2&gt;
      &lt;form id="updateScore"&gt;
        &lt;div class="grid"&gt;
          &lt;div class="form-group full"&gt;
            &lt;label for="scoreMatchId"&gt;Select Match&lt;/label&gt;
            &lt;select id="scoreMatchId" required&gt;
              &lt;option value=""&gt;-- Select match --&lt;/option&gt;
            &lt;/select&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="homeScore"&gt;Home Score&lt;/label&gt;
            &lt;input type="number" id="homeScore" min="0" value="0"&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="awayScore"&gt;Away Score&lt;/label&gt;
            &lt;input type="number" id="awayScore" min="0" value="0"&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="minute"&gt;Minute&lt;/label&gt;
            &lt;input type="number" id="minute" min="0" placeholder="e.g. 67"&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="status"&gt;Status&lt;/label&gt;
            &lt;select id="status"&gt;
              &lt;option value="scheduled"&gt;Scheduled&lt;/option&gt;
              &lt;option value="live"&gt;Live&lt;/option&gt;
              &lt;option value="halftime"&gt;Halftime&lt;/option&gt;
              &lt;option value="finished"&gt;Finished&lt;/option&gt;
            &lt;/select&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class="actions"&gt;
          &lt;button type="submit" class="btn-primary"&gt;Update Score&lt;/button&gt;
        &lt;/div&gt;
      &lt;/form&gt;
    &lt;/section&gt;

    &lt;section&gt;
      &lt;h2&gt;Add Match Event (Goal, Card, etc.)&lt;/h2&gt;
      &lt;form id="addEvent"&gt;
        &lt;div class="grid"&gt;
          &lt;div class="form-group full"&gt;
            &lt;label for="eventMatchId"&gt;Select Match&lt;/label&gt;
            &lt;select id="eventMatchId" required&gt;
              &lt;option value=""&gt;-- Select match --&lt;/option&gt;
            &lt;/select&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="eventType"&gt;Event Type&lt;/label&gt;
            &lt;select id="eventType"&gt;
              &lt;option value="goal"&gt;Goal&lt;/option&gt;
              &lt;option value="yellow_card"&gt;Yellow Card&lt;/option&gt;
              &lt;option value="red_card"&gt;Red Card&lt;/option&gt;
              &lt;option value="substitution"&gt;Substitution&lt;/option&gt;
              &lt;option value="penalty"&gt;Penalty&lt;/option&gt;
            &lt;/select&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="eventTeam"&gt;Team&lt;/label&gt;
            &lt;input type="text" id="eventTeam" placeholder="e.g. Manchester United"&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="eventPlayer"&gt;Player&lt;/label&gt;
            &lt;input type="text" id="eventPlayer" placeholder="e.g. Marcus Rashford"&gt;
          &lt;/div&gt;
          &lt;div class="form-group"&gt;
            &lt;label for="eventMinute"&gt;Minute&lt;/label&gt;
            &lt;input type="number" id="eventMinute" min="0" placeholder="e.g. 23"&gt;
          &lt;/div&gt;
          &lt;div class="form-group full"&gt;
            &lt;label for="eventDesc"&gt;Description&lt;/label&gt;
            &lt;input type="text" id="eventDesc" placeholder="Optional description"&gt;
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;div class="actions"&gt;
          &lt;button type="submit" class="btn-primary"&gt;Add Event&lt;/button&gt;
        &lt;/div&gt;
      &lt;/form&gt;
    &lt;/section&gt;

    &lt;section&gt;
      &lt;h2&gt;Active Matches&lt;/h2&gt;
      &lt;div class="match-list" id="matchList"&gt;&lt;/div&gt;
    &lt;/section&gt;
  &lt;/div&gt;

  &lt;div class="toast" id="toast"&gt;&lt;/div&gt;
</code></pre>
<p>The three forms use <code>id</code> attributes (<code>createMatch</code>, <code>updateScore</code>, <code>addEvent</code>) so the JavaScript can attach submit handlers. The match dropdowns (<code>scoreMatchId</code> and <code>eventMatchId</code>) are populated dynamically when the page loads. The <code>matchList</code> div is the container for the list of active matches. The toast element sits outside the main container so it can be fixed to the viewport.</p>
<h3 id="heading-admin-javascript-logic">Admin JavaScript Logic</h3>
<p>The script block handles all interaction between the admin page and the server. It defines helper functions for showing notifications, fetching matches, updating the UI, and submitting data. When the page loads or after any action (create, update, or event submission), the UI refreshes so the latest match data is always visible.</p>
<pre><code class="language-javascript">  &lt;script&gt;
    const API = '/api';
    const toast = document.getElementById('toast');

    function showToast(msg, isError = false) {
      toast.textContent = msg;
      toast.className = 'toast show' + (isError ? ' error' : '');
      setTimeout(() =&gt; toast.classList.remove('show'), 3000);
    }

    async function fetchMatches() {
      const res = await fetch(`${API}/matches`);
      return res.json();
    }

    function populateSelects(matches) {
      const opts = matches.map(m =&gt; `&lt;option value="\({m.id}"&gt;\){m.homeTeam} vs ${m.awayTeam}&lt;/option&gt;`).join('');
      const html = '&lt;option value=""&gt;-- Select match --&lt;/option&gt;' + opts;
      document.getElementById('scoreMatchId').innerHTML = html;
      document.getElementById('eventMatchId').innerHTML = html;
    }

    function renderMatchList(matches) {
      const list = document.getElementById('matchList');
      if (!matches.length) {
        list.innerHTML = '&lt;p style="color: var(--text-muted);"&gt;No matches yet. Create one above.&lt;/p&gt;';
        return;
      }
      list.innerHTML = matches.map(m =&gt; `
        &lt;div class="match-card" data-id="${m.id}"&gt;
          &lt;div class="match-info"&gt;
            &lt;div class="match-teams"&gt;\({m.homeTeam} vs \){m.awayTeam}&lt;/div&gt;
            &lt;div class="match-meta"&gt;\({m.league} • \){m.status} • ${m.minute}'&lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="match-score"&gt;\({m.homeScore} - \){m.awayScore}&lt;/div&gt;
          &lt;div class="match-actions"&gt;
            &lt;button class="btn-secondary" onclick="quickScore('\({m.id}', \){m.homeScore}, ${m.awayScore})"&gt;Update&lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      `).join('');
    }

    function quickScore(id, h, a) {
      document.getElementById('scoreMatchId').value = id;
      document.getElementById('homeScore').value = h;
      document.getElementById('awayScore').value = a;
    }

    async function loadMatches() {
      const matches = await fetchMatches();
      populateSelects(matches);
      renderMatchList(matches);
    }

    document.getElementById('createMatch').onsubmit = async (e) =&gt; {
      e.preventDefault();
      const body = {
        homeTeam: document.getElementById('homeTeam').value.trim(),
        awayTeam: document.getElementById('awayTeam').value.trim(),
        league: document.getElementById('league').value.trim() || 'Premier League',
        venue: document.getElementById('venue').value.trim() || 'TBD',
        kickoff: document.getElementById('kickoff').value
          ? new Date(document.getElementById('kickoff').value).toISOString()
          : new Date().toISOString(),
      };
      try {
        const res = await fetch(`${API}/matches`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(body),
        });
        const data = await res.json();
        if (res.ok) {
          showToast('Match created!');
          document.getElementById('createMatch').reset();
          loadMatches();
        } else showToast(data.error || 'Failed', true);
      } catch (err) {
        showToast('Network error', true);
      }
    };

    document.getElementById('updateScore').onsubmit = async (e) =&gt; {
      e.preventDefault();
      const id = document.getElementById('scoreMatchId').value;
      const body = {
        homeScore: parseInt(document.getElementById('homeScore').value, 10),
        awayScore: parseInt(document.getElementById('awayScore').value, 10),
        minute: parseInt(document.getElementById('minute').value, 10) || undefined,
        status: document.getElementById('status').value,
      };
      try {
        const res = await fetch(`\({API}/matches/\){id}/score`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(body),
        });
        const data = await res.json();
        if (res.ok) {
          showToast('Score updated!');
          loadMatches();
        } else showToast(data.error || 'Failed', true);
      } catch (err) {
        showToast('Network error', true);
      }
    };

    document.getElementById('addEvent').onsubmit = async (e) =&gt; {
      e.preventDefault();
      const id = document.getElementById('eventMatchId').value;
      const body = {
        type: document.getElementById('eventType').value,
        team: document.getElementById('eventTeam').value.trim(),
        player: document.getElementById('eventPlayer').value.trim(),
        minute: parseInt(document.getElementById('eventMinute').value, 10) || undefined,
        description: document.getElementById('eventDesc').value.trim() || undefined,
      };
      try {
        const res = await fetch(`\({API}/matches/\){id}/events`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(body),
        });
        const data = await res.json();
        if (res.ok) {
          showToast('Event added!');
          loadMatches();
        } else showToast(data.error || 'Failed', true);
      } catch (err) {
        showToast('Network error', true);
      }
    };

    loadMatches();
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Explanation of each part:</p>
<ul>
<li><p><code>showToast</code>: updates the toast text and adds the show class to trigger the CSS animation. The isError parameter switches the toast to a red background for error messages. The setTimeout removes the show class after 3 seconds so the toast slides back out.</p>
</li>
<li><p><code>fetchMatches</code>: calls the GET /api/matches endpoint and returns the parsed JSON so the UI can display the latest data.</p>
</li>
<li><p><code>populateSelects</code>: builds option elements from the matches array and injects them into both dropdowns, so the same match list appears in the Update Score and Add Event forms.</p>
</li>
<li><p><code>renderMatchList</code>: either shows a placeholder when there are no matches or renders each match as a card with team names, scores, league, status, and an Update button.</p>
</li>
<li><p><code>quickScore</code>: pre-fills the Update Score form when you click the Update button on a match card, so you can adjust the score without re-selecting the match.</p>
</li>
<li><p><code>loadMatches</code>: fetches matches, populates the dropdowns, and renders the list. It runs on page load and after every successful create, update, or event submission.</p>
</li>
<li><p><code>onsubmit</code>: calls e.preventDefault() to stop the default form submission, builds a request body from the form values, sends a fetch request to the appropriate endpoint, and on success shows a toast and calls loadMatches to refresh the UI.</p>
</li>
</ul>
<h2 id="heading-how-to-build-the-live-viewer-interface">How to Build the Live Viewer Interface</h2>
<p>The viewer interface displays real-time match updates and connects to the Server-Sent Events endpoint so it can receive data the moment the server pushes it.</p>
<p>Unlike the admin page, the viewer is read-only: it shows live scores, match events, and status updates without requiring user input. The page uses a dark theme and a connection indicator so users can see whether the real-time stream is active.</p>
<p>Now create the file at <code>public/viewer.html</code>:</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;title&gt;Live Football Scores&lt;/title&gt;
  &lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
  &lt;link rel="preconnect" href="https://fonts.gstatic.com" crossorigin&gt;
  &lt;link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
  &lt;style&gt;
    :root {
      --bg: #0a0e14;
      --surface: #131a24;
      --accent: #00d26a;
      --accent-glow: rgba(0, 210, 106, 0.3);
      --text: #e8edf2;
      --text-muted: #8b9aab;
      --border: #2d3a4d;
      --live: #ff4757;
    }
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: 'Outfit', sans-serif;
      background: var(--bg);
      color: var(--text);
      min-height: 100vh;
      padding: 2rem;
    }
    .container { max-width: 700px; margin: 0 auto; }
    header { text-align: center; margin-bottom: 2rem; }
    .status {
      display: inline-flex;
      align-items: center;
      gap: 0.5rem;
      font-size: 0.85rem;
      color: var(--text-muted);
    }
    .status-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      background: var(--text-muted);
      animation: pulse 2s infinite;
    }
    .status-dot.connected {
      background: var(--accent);
      box-shadow: 0 0 0 3px var(--accent-glow);
    }
    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.5; }
    }
    .match-card {
      background: var(--surface);
      border-radius: 16px;
      padding: 1.5rem;
      margin-bottom: 1rem;
      border: 1px solid var(--border);
      transition: border-color 0.2s, box-shadow 0.2s;
    }
    .match-card.live {
      border-color: var(--live);
      box-shadow: 0 0 0 1px rgba(255, 71, 87, 0.2);
    }
    .match-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-bottom: 1rem;
    }
    .league { 
      font-size: 0.8rem; 
      color: var(--text-muted); 
      margin-bottom: 0.25rem; 
    }
    .match-teams {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      margin: 1rem 0;
    }
    .team { flex: 1; text-align: center; font-weight: 600; font-size: 1.1rem; }
    .team.home { text-align: left; }
    .team.away { text-align: right; }
    .score-box {
      display: flex;
      align-items: center;
      justify-content: center;
      min-width: 80px;
      gap: 0.5rem;
    }
    .score { 
      font-size: 2rem; 
      font-weight: 700; 
      color: var(--accent); 
     }
    .status-badge { 
      font-size: 0.7rem; 
      padding: 0.2rem 0.5rem; 
      border-radius: 4px; 
      font-weight: 600; 
     }
    .status-badge.live { background: var(--live); color: white; }
    .status-badge.finished { background: var(--border); color: var(--text-muted); }
    .status-badge.scheduled { background: var(--accent); color: var(--bg); }
    .match-meta { font-size: 0.85rem; color: var(--text-muted); margin-top: 0.5rem; }
    .events { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--border); }
    .events h4 { font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.5rem; }
    .event { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; padding: 0.35rem 0; border-bottom: 1px solid var(--border); }
    .event:last-child { border-bottom: none; }
    .event-icon { width: 24px; text-align: center; font-size: 1rem; }
    .event.goal .event-icon { color: var(--accent); }
    .event.yellow_card .event-icon { color: #ffd93d; }
    .event.red_card .event-icon { color: var(--live); }
    .feed { margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
    .feed h3 { font-size: 1rem; margin-bottom: 1rem; color: var(--text-muted); }
    .feed-item { font-size: 0.85rem; padding: 0.5rem 0; color: var(--text-muted); border-bottom: 1px solid var(--border); }
    .feed-item:last-child { border-bottom: none; }
    .feed-item strong { color: var(--text); }
    .empty { text-align: center; padding: 3rem 2rem; color: var(--text-muted); }
    .empty-icon { font-size: 3rem; margin-bottom: 1rem; opacity: 0.5; }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div class="container"&gt;
    &lt;header&gt;
      &lt;h1&gt;⚽ Live Football Scores&lt;/h1&gt;
      &lt;div class="status" id="status"&gt;
        &lt;span class="status-dot" id="statusDot"&gt;&lt;/span&gt;
        &lt;span id="statusText"&gt;Connecting...&lt;/span&gt;
      &lt;/div&gt;
    &lt;/header&gt;

    &lt;div id="matches"&gt;&lt;/div&gt;

    &lt;div class="feed" id="feedSection"&gt;
      &lt;h3&gt;Live Feed&lt;/h3&gt;
      &lt;div id="feed"&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
</code></pre>
<p>Explanation of each part:</p>
<ul>
<li><p><code>header</code>: displays the page title and a connection indicator so users know whether the real-time stream is active.</p>
</li>
<li><p><code>status dot</code>: a small circle that pulses while disconnected and turns green with a glow when the SSE connection is established.</p>
</li>
<li><p><code>matches container</code>: the div with id="matches" is where match cards will be rendered dynamically by JavaScript as data arrives.</p>
</li>
<li><p><code>feed section</code>: shows a chronological list of live updates so users can see recent events at a glance.</p>
</li>
<li><p><code>CSS theme</code>: uses dark colors and custom properties so the look can be adjusted in one place. The live badge and border styles highlight matches that are in progress.</p>
</li>
<li><p><code>Server-Sent Events integration</code>: JavaScript (added in the next step) will connect to /api/events and update this page whenever new data arrives.</p>
</li>
</ul>
<p>The header shows the title and a connection status indicator. The <code>matches</code> div is the container for match cards, populated by JavaScript. The <code>feed</code> div displays the live feed of recent updates.</p>
<h3 id="heading-viewer-javascript-logic">Viewer JavaScript Logic</h3>
<p>The script powers the live viewer interface by maintaining an in-memory collection of matches and a feed of recent updates. It connects to the Server-Sent Events endpoint so data flows from the server to the browser in real time. When messages arrive, the page updates automatically to show the latest scores, events, and match details.</p>
<pre><code class="language-javascript">  &lt;script&gt;
    const API = '/api';
    const matches = new Map();
    const feed = [];
    const MAX_FEED = 20;

    const statusDot = document.getElementById('statusDot');
    const statusText = document.getElementById('statusText');
    const matchesEl = document.getElementById('matches');
    const feedEl = document.getElementById('feed');

    function setStatus(connected) {
      statusDot.classList.toggle('connected', connected);
      statusText.textContent = connected ? 'Live' : 'Reconnecting...';
    }

    function renderMatches() {
      const list = Array.from(matches.values()).sort(
        (a, b) =&gt; new Date(b.createdAt) - new Date(a.createdAt)
      );
      if (!list.length) {
        matchesEl.innerHTML = `
          &lt;div class="empty"&gt;
            &lt;div class="empty-icon"&gt;⚽&lt;/div&gt;
            &lt;p&gt;No matches yet. Updates will appear here in real-time.&lt;/p&gt;
          &lt;/div&gt;
        `;
        return;
      }
      matchesEl.innerHTML = list.map(m =&gt; `
        &lt;div class="match-card \({m.status === 'live' ? 'live' : ''}" data-id="\){m.id}"&gt;
          &lt;div class="match-header"&gt;
            &lt;div&gt;
              &lt;div class="league"&gt;${m.league}&lt;/div&gt;
              &lt;div class="match-meta"&gt;\({m.venue} • \){m.kickoff ? new Date(m.kickoff).toLocaleString() : ''}&lt;/div&gt;
            &lt;/div&gt;
            &lt;span class="status-badge \({m.status}"&gt;\){m.status}&lt;/span&gt;
          &lt;/div&gt;
          &lt;div class="match-teams"&gt;
            &lt;div class="team home"&gt;${m.homeTeam}&lt;/div&gt;
            &lt;div class="score-box"&gt;
              &lt;span class="score"&gt;${m.homeScore}&lt;/span&gt;
              &lt;span&gt;-&lt;/span&gt;
              &lt;span class="score"&gt;${m.awayScore}&lt;/span&gt;
            &lt;/div&gt;
            &lt;div class="team away"&gt;${m.awayTeam}&lt;/div&gt;
          &lt;/div&gt;
          \({m.minute ? `&lt;div class="match-meta"&gt;\){m.minute}'&lt;/div&gt;` : ''}
          ${m.events?.length ? `
            &lt;div class="events"&gt;
              &lt;h4&gt;Events&lt;/h4&gt;
              ${m.events.map(e =&gt; `
                &lt;div class="event ${e.type}"&gt;
                  &lt;span class="event-icon"&gt;${getEventIcon(e.type)}&lt;/span&gt;
                  &lt;span&gt;\({e.minute}' \){e.player} (\({e.team}) - \){e.description || e.type}&lt;/span&gt;
                &lt;/div&gt;
              `).join('')}
            &lt;/div&gt;
          ` : ''}
        &lt;/div&gt;
      `).join('');
    }

    function getEventIcon(type) {
      const icons = { goal: '⚽', yellow_card: '🟨', red_card: '🟥', substitution: '🔄', penalty: '⚽' };
      return icons[type] || '•';
    }

    function renderFeed() {
      const items = feed.slice(-MAX_FEED).reverse();
      feedEl.innerHTML = items.length
        ? items.map(f =&gt; `&lt;div class="feed-item"&gt;${f}&lt;/div&gt;`).join('')
        : '&lt;div class="feed-item"&gt;Waiting for updates...&lt;/div&gt;';
    }

    function addFeedItem(type, msg) {
      const time = new Date().toLocaleTimeString();
      feed.push(`&lt;strong&gt;\({time}&lt;/strong&gt; | \){msg}`);
      if (feed.length &gt; MAX_FEED) feed.shift();
      renderFeed();
    }

    function handleMessage(data) {
      if (data.match) {
        matches.set(data.match.id, data.match);
        renderMatches();
      }
      if (data.id &amp;&amp; data.homeTeam &amp;&amp; data.awayTeam) {
        matches.set(data.id, data);
        renderMatches();
      }
      if (data.type === 'match_created' &amp;&amp; data.match) {
        addFeedItem('match', `New match: \({data.match.homeTeam} vs \){data.match.awayTeam}`);
      }
      if (data.type === 'score_update') {
        const m = matches.get(data.matchId);
        if (m) {
          m.homeScore = data.homeScore;
          m.awayScore = data.awayScore;
          m.minute = data.minute;
          m.status = data.status;
          matches.set(data.matchId, m);
          addFeedItem('score', `\({m.homeTeam} \){data.homeScore}-\({data.awayScore} \){m.awayTeam} (${data.minute || '?'}')`);
          renderMatches();
        }
      }
      if (data.type === 'match_event' &amp;&amp; data.event) {
        const m = matches.get(data.matchId);
        if (m) {
          m.events = m.events || [];
          m.events.push(data.event);
          if (data.event.type === 'goal') {
            if (data.event.team === m.homeTeam) m.homeScore++;
            else if (data.event.team === m.awayTeam) m.awayScore++;
          }
          matches.set(data.matchId, m);
          addFeedItem('event', `\({data.event.type}: \){data.event.player} (\({data.event.team}) - \){data.event.minute}'`);
          renderMatches();
        }
      }
    }

    function handleSSEMessage(msg) {
      try {
        const data = JSON.parse(msg);
        if (data.topic &amp;&amp; /^sports\/football\/match\/([^/]+)$/.test(data.topic) &amp;&amp; data.id) {
          matches.set(data.id, data);
        }
        handleMessage(data);
      } catch (e) {}
    }

    function connectSSE() {
      const es = new EventSource(`${API}/events`);
      es.onopen = () =&gt; setStatus(true);
      es.onerror = () =&gt; {
        setStatus(false);
        es.close();
        setTimeout(connectSSE, 3000);
      };
      es.onmessage = (e) =&gt; handleSSEMessage(e.data);
    }

    async function loadInitial() {
      try {
        const res = await fetch(`${API}/matches`);
        const list = await res.json();
        list.forEach(m =&gt; matches.set(m.id, m));
        renderMatches();
      } catch (e) {
        matchesEl.innerHTML = '&lt;div class="empty"&gt;&lt;p&gt;Could not load matches. Is the server running?&lt;/p&gt;&lt;/div&gt;';
      }
    }

    loadInitial();
    connectSSE();
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>Explanation of each part:</p>
<ul>
<li><p>The <code>matches Map</code>: stores match objects keyed by ID so updates can be applied efficiently without searching arrays.</p>
</li>
<li><p>The <code>feed array</code>: keeps a small history of recent events (limited to MAX_FEED) so the live feed remains lightweight.</p>
</li>
<li><p><code>setStatus</code>: toggles the connected class on the status dot and updates the status text to “Live” or “Reconnecting…” so users know connection status.</p>
</li>
<li><p><code>renderMatches</code>: converts the Map to a sorted array (newest first). If there are no matches, it displays an empty state. Otherwise it renders cards showing league, venue, teams, scores, status badge, minute, and events.</p>
</li>
<li><p><code>getEventIcon</code>: returns an emoji for each event type so events are visually identifiable (goal, card, substitution, and so on).</p>
</li>
<li><p><code>renderFeed</code>: displays the live feed items or a placeholder message when no updates exist.</p>
</li>
<li><p><code>addFeedItem</code>: appends a timestamped message to the feed, keeps only the latest items, and re-renders the feed.</p>
</li>
<li><p><code>handleMessage</code>: processes incoming data. It updates the matches Map for full match objects, score updates, and match events. For score updates and goals it adjusts scores and adds feed items so the viewer reflects real-time changes.</p>
</li>
<li><p><code>handleSSEMessage</code>: parses the Server-Sent Events payload and forwards it to handleMessage. If the message contains a match topic and full match data, it stores it in the Map.</p>
</li>
<li><p><code>connectSSE</code>: creates an EventSource connection to /api/events. On open it marks the connection as live. On error it closes and retries after three seconds so transient network issues do not break the stream.</p>
</li>
<li><p><code>loadInitial</code>: fetches existing matches on page load so the viewer displays data even before real-time updates arrive.</p>
</li>
</ul>
<h2 id="heading-how-to-build-the-home-page">How to Build the Home Page</h2>
<p>The home page (<code>public/index.html</code>) is a simple landing page that links to the viewer and admin interfaces. It uses a centered card layout with two buttons. The primary button (green) goes to the viewer, and the secondary button (outlined) goes to the admin. The page uses the same dark theme and Outfit font for consistency. There is no JavaScript – it's purely static HTML and CSS.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;title&gt;Football Scores - MQTT Real-Time&lt;/title&gt;
  &lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
  &lt;link rel="preconnect" href="https://fonts.gstatic.com" crossorigin&gt;
  &lt;link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
  &lt;style&gt;
    :root {
      --bg: #0a0e14;
      --surface: #131a24;
      --accent: #00d26a;
      --text: #e8edf2;
      --text-muted: #8b9aab;
    }
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body {
      font-family: 'Outfit', sans-serif;
      background: var(--bg);
      color: var(--text);
      min-height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 2rem;
    }
    .card {
      background: var(--surface);
      border-radius: 16px;
      padding: 2rem;
      max-width: 400px;
      text-align: center;
      border: 1px solid rgba(255,255,255,0.06);
    }
    h1 { font-size: 1.5rem; margin-bottom: 0.5rem; }
    p { color: var(--text-muted); font-size: 0.95rem; margin-bottom: 1.5rem; }
    .links { display: flex; flex-direction: column; gap: 0.75rem; }
    a {
      display: block;
      padding: 1rem 1.5rem;
      background: var(--accent);
      color: var(--bg);
      text-decoration: none;
      font-weight: 600;
      border-radius: 10px;
      transition: opacity 0.2s;
    }
    a:hover { opacity: 0.9; }
    a.secondary {
      background: transparent;
      color: var(--text);
      border: 1px solid rgba(255,255,255,0.15);
    }
  &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;div class="card"&gt;
    &lt;h1&gt;⚽ Football Scores&lt;/h1&gt;
    &lt;p&gt;Real-time updates via MQTT &amp; Mosquitto&lt;/p&gt;
    &lt;div class="links"&gt;
      &lt;a href="/viewer.html"&gt;View Live Scores&lt;/a&gt;
      &lt;a href="/admin.html" class="secondary"&gt;Admin - Upload Scores&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>The Express server serves <code>index.html</code> when you visit the root URL (<code>http://localhost:3000/</code>) because the <code>express.static</code> middleware serves files from the <code>public</code> folder, and Express automatically serves <code>index.html</code> when the request path is <code>/</code>.</p>
<h2 id="heading-how-to-run-and-test-the-system">How to Run and Test the System</h2>
<p>Start the MQTT broker (Docker or local install).</p>
<p>Then start the Express server:</p>
<pre><code class="language-bash">npm start
</code></pre>
<p>Next, open <code>http://localhost:3000/admin.html</code> in the admin panel. Create a new match (for example, Manchester United vs Liverpool).</p>
<p>Open <code>http://localhost:3000/viewer.html</code> in another tab or window. Then update the score or add an event in the admin panel. The viewer should update within a second without refreshing.</p>
<h2 id="heading-how-to-extend-the-system-for-production">How to Extend the System for Production</h2>
<p>The current implementation uses in-memory storage. For production, you should:</p>
<ul>
<li><p><strong>Add a database</strong>: Store matches in PostgreSQL, MongoDB, or another database. Load matches on startup and persist every create, update, and event.</p>
</li>
<li><p><strong>Add authentication</strong>: Protect the admin routes with JSON Web Tokens (JWT) or session-based auth so only authorized users can upload scores.</p>
</li>
<li><p><strong>Add validation</strong>: Validate request bodies with a library such as Joi or Zod to prevent invalid data.</p>
</li>
<li><p><strong>Enable TLS</strong>: Use HTTPS for the Express server and secure WebSockets or MQTTS for the broker in production.</p>
</li>
<li><p><strong>Scale horizontally</strong>: If you run multiple server instances, each will have its own MQTT connection and SSE clients. The MQTT broker will deliver messages to all subscribers, so each instance will receive updates and forward them to its connected viewers.</p>
</li>
</ul>
<h2 id="heading-api-reference">API Reference</h2>
<p>For quick reference, here are the endpoints your server exposes:</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Endpoint</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>GET</td>
<td><code>/api/matches</code></td>
<td>Returns all matches as a JSON array</td>
</tr>
<tr>
<td>POST</td>
<td><code>/api/matches</code></td>
<td>Creates a new match. Body: <code>{ homeTeam, awayTeam, league?, venue?, kickoff? }</code></td>
</tr>
<tr>
<td>PATCH</td>
<td><code>/api/matches/:id/score</code></td>
<td>Updates a match score. Body: <code>{ homeScore?, awayScore?, minute?, status? }</code></td>
</tr>
<tr>
<td>POST</td>
<td><code>/api/matches/:id/events</code></td>
<td>Adds an event. Body: <code>{ type?, team, player?, minute?, description? }</code></td>
</tr>
<tr>
<td>GET</td>
<td><code>/api/events</code></td>
<td>Server-Sent Events stream for real-time updates</td>
</tr>
</tbody></table>
<p>The <code>status</code> field can be <code>scheduled</code>, <code>live</code>, <code>halftime</code>, or <code>finished</code>. The <code>type</code> field for events can be <code>goal</code>, <code>yellow_card</code>, <code>red_card</code>, <code>substitution</code>, or <code>penalty</code>.</p>
<h2 id="heading-troubleshooting">Troubleshooting</h2>
<p>You might come across various issues as you build this. Here are some common ones:</p>
<p><strong>The server cannot connect to the MQTT broker.</strong> Check that Mosquitto is running. If you use Docker, run <code>docker ps</code> to verify the container is up. If you use the public broker, ensure you have internet connectivity and that your firewall allows outbound connections on port 1883.</p>
<p><strong>The viewer does not update when you change scores.</strong> Open the browser developer tools and check the Network tab. The <code>/api/events</code> request should show a pending state (it stays open). If it fails or closes, check the server logs for errors. Ensure you are not behind a proxy that buffers or closes long-lived connections.</p>
<p><strong>Matches disappear when you restart the server.</strong> The current implementation stores matches in memory. Restarting the server clears the data. Add a database as described in the production section to persist matches across restarts.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you built a real-time football sports update system using MQTT, Mosquitto, and Express. You've learned how to:</p>
<ul>
<li><p>Connect an Express server to an MQTT broker</p>
</li>
<li><p>Publish match and score updates to MQTT topics</p>
</li>
<li><p>Subscribe to topics and forward messages to browsers via Server-Sent Events</p>
</li>
<li><p>Build an admin interface for creating matches and updating scores</p>
</li>
<li><p>Build a viewer interface that displays live updates without page refreshes</p>
</li>
</ul>
<p>The same pattern applies to other real-time systems: IoT dashboards, live notifications, collaborative editing, and more. MQTT gives you a reliable, scalable messaging layer, and Server-Sent Events gives you a simple way to push updates to web clients.</p>
<p>The code in this tutorial gives you a solid foundation. Try adding features such as match filtering by league, historical event logs, or push notifications to make the system your own.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Django REST APIs for Performance: Profiling, Caching, and Scaling. ]]>
                </title>
                <description>
                    <![CDATA[ Performance problems in APIs rarely start as performance problems. They usually start as small design decisions that worked perfectly when the application had ten users, ten records, or a single developer testing locally. Over time, as traffic increa... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-optimize-django-rest-apis-for-performance/</link>
                <guid isPermaLink="false">6994b1d13e0696149c7c229c</guid>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ django rest framework ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ caching ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Performance Optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ scalability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mari ]]>
                </dc:creator>
                <pubDate>Tue, 17 Feb 2026 18:22:09 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1771352481135/11be538b-aaf5-4c1e-8ee2-99deea5f180e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Performance problems in APIs rarely start as performance problems. They usually start as small design decisions that worked perfectly when the application had ten users, ten records, or a single developer testing locally. Over time, as traffic increases and data grows, those same decisions begin to slow everything down.</p>
<p>In this article, we’ll walk step by step through how performance issues arise in Django REST APIs, how to see them clearly using profiling tools, and how to fix them using query optimization, caching, pagination, and basic scaling strategies.</p>
<p>This article will be most useful for developers who already understand Django, the Django REST Framework, and REST concepts, but are new to performance optimization.</p>
<h3 id="heading-what-well-cover">What we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-django-rest-apis-become-slow">Why Django REST APIs Become Slow</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-profiling-finding-the-real-bottlenecks">Profiling: Finding the Real Bottlenecks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-logging-sql-queries">Logging SQL Queries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary-and-next-steps">Summary and Next Steps</a></p>
</li>
</ul>
<h2 id="heading-why-django-rest-apis-become-slow">Why Django REST APIs Become Slow</h2>
<p>Before optimizing anything, it’s important to understand why APIs become slow in the first place.</p>
<p>Most performance issues in Django REST APIs come from three main sources:</p>
<ol>
<li><p>Too many database queries</p>
</li>
<li><p>Doing expensive work repeatedly</p>
</li>
<li><p>Returning more data than necessary</p>
</li>
</ol>
<p>Django is fast by default, but it does exactly what you ask it to do. If your API endpoint triggers 300 database queries, Django will happily run all 300.</p>
<p>Now let’s look at some common causes of performance issues in Django REST APIs.</p>
<h3 id="heading-1-n1-query-problems-in-serializers">1. N+1 Query Problems in Serializers</h3>
<p>This happens when you loop over objects and access related fields, causing a separate query for each object.</p>
<pre><code class="lang-python"><span class="hljs-comment"># models.py</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Author</span>(<span class="hljs-params">models.Model</span>):</span>
    name = models.CharField(max_length=<span class="hljs-number">100</span>)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span>(<span class="hljs-params">models.Model</span>):</span>
    title = models.CharField(max_length=<span class="hljs-number">200</span>)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

<span class="hljs-comment"># views.py (naive approach)</span>
posts = Post.objects.all()
<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-comment"># This triggers a query per post to fetch the author</span>
    print(post.author.name)
</code></pre>
<p>If you have 100 posts, this runs 101 queries: 1 for posts and 100 for authors. Django lazily loads related objects by default, so without intervention, your API performs repetitive database work that slows response times.</p>
<h3 id="heading-2-fetching-related-objects-inefficiently">2. Fetching Related Objects Inefficiently</h3>
<pre><code class="lang-python"><span class="hljs-comment"># Naive queryset fetching all related objects separately</span>
posts = Post.objects.all()
authors = [post.author <span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts]  <span class="hljs-comment"># triggers extra queries per post</span>
</code></pre>
<p>Each access to <code>post.author</code> triggers a new query. Even though you already fetched all posts, Django lazily loads related objects by default. This creates many extra queries, slowing down your API.</p>
<h3 id="heading-3-serializing-large-datasets-without-pagination">3. Serializing Large Datasets Without Pagination</h3>
<p>Returning large query sets all at once can slow down your API and increase memory usage.</p>
<pre><code class="lang-python"><span class="hljs-comment"># views.py</span>
<span class="hljs-keyword">from</span> rest_framework.response <span class="hljs-keyword">import</span> Response
<span class="hljs-keyword">from</span> rest_framework.decorators <span class="hljs-keyword">import</span> api_view
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Post
<span class="hljs-keyword">from</span> .serializers <span class="hljs-keyword">import</span> PostSerializer

<span class="hljs-meta">@api_view(['GET'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">all_posts</span>(<span class="hljs-params">request</span>):</span>
    posts = Post.objects.all()  <span class="hljs-comment"># retrieves all posts at once</span>
    serializer = PostSerializer(posts, many=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> Response(serializer.data)
</code></pre>
<p>If your database has thousands of posts, this endpoint fetches everything in memory, serializes it, and sends it over the network. It’s slow and can crash under load. Later, we’ll learn to paginate results efficiently.</p>
<h3 id="heading-4-recomputing-expensive-work-repeatedly">4. Recomputing Expensive Work Repeatedly</h3>
<p>Some endpoints calculate the same values on every request instead of caching or precomputing.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">expensive_view</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-comment"># Simulate expensive computation</span>
    result = sum([i**<span class="hljs-number">2</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1000000</span>)])
    <span class="hljs-keyword">return</span> JsonResponse({<span class="hljs-string">"result"</span>: result})
</code></pre>
<p>Even if the data doesn’t change often, this computation happens on every request, consuming CPU time unnecessarily.  </p>
<p>Performance optimization is about reducing unnecessary work.  </p>
<p>At this point, it might be tempting to jump straight into fixes like caching responses or optimizing database queries. But doing that without evidence often leads to wasted effort or even new problems.</p>
<p>Before changing anything, you need to understand where your API is actually spending time. Is it the database? Is it serialization? Is it Python code running repeatedly on every request? This is where profiling becomes essential.</p>
<h2 id="heading-profiling-finding-the-real-bottlenecks">Profiling: Finding the Real Bottlenecks</h2>
<p>Optimizing without profiling is guessing. Profiling helps you answer one question:</p>
<blockquote>
<p>Where is my API actually spending time?</p>
</blockquote>
<p>In practice, profiling means observing an API while it runs and collecting data about what it’s doing. This includes how many database queries are executed, how long those queries take, and how much time is spent in Python code, such as serializers or business logic.</p>
<p>By profiling first, you avoid making assumptions and can focus on fixing the parts of your API that are truly slowing things down.</p>
<h3 id="heading-measuring-query-count-in-a-view">Measuring Query Count in a View</h3>
<p>During development, Django keeps track of all executed queries. You can inspect them directly:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> connection
<span class="hljs-keyword">from</span> rest_framework.decorators <span class="hljs-keyword">import</span> api_view
<span class="hljs-keyword">from</span> rest_framework.response <span class="hljs-keyword">import</span> Response
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Post
<span class="hljs-keyword">from</span> .serializers <span class="hljs-keyword">import</span> PostSerializer

<span class="hljs-meta">@api_view(["GET"])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post_list</span>(<span class="hljs-params">request</span>):</span>
    posts = Post.objects.all()
    serializer = PostSerializer(posts, many=<span class="hljs-literal">True</span>)

    response = Response(serializer.data)

    print(<span class="hljs-string">f"Total queries executed: <span class="hljs-subst">{len(connection.queries)}</span>"</span>)

    <span class="hljs-keyword">return</span> response
</code></pre>
<p>If this prints 101 queries for 100 posts, you likely have an N+1 problem. This simple check confirms whether the database layer is the bottleneck.</p>
<p>One of the easiest ways to profile Django applications during development is by using tools that expose this information directly while requests are being processed.</p>
<h3 id="heading-using-the-django-debug-toolbar">Using the Django Debug Toolbar</h3>
<p>The Django Debug Toolbar is one of the simplest ways to understand performance during development. It acts as a lightweight profiling tool that shows what happens behind the scenes when a request is handled.</p>
<p>It shows you:</p>
<ul>
<li><p>How many SQL queries were executed</p>
</li>
<li><p>How long each query took</p>
</li>
<li><p>whether queries are duplicated</p>
</li>
<li><p>Which parts of the request lifecycle are slow</p>
</li>
</ul>
<h4 id="heading-how-to-install-and-enable-the-django-debug-toolbar">How to Install and Enable the Django Debug Toolbar</h4>
<p>First, install it:</p>
<pre><code class="lang-bash">pip install django-debug-toolbar
</code></pre>
<p>In settings.py:</p>
<pre><code class="lang-bash">INSTALLED_APPS = [
    ...
    <span class="hljs-string">"debug_toolbar"</span>,
]

MIDDLEWARE = [
    ...
    <span class="hljs-string">"debug_toolbar.middleware.DebugToolbarMiddleware"</span>,
]

INTERNAL_IPS = [
    <span class="hljs-string">"127.0.0.1"</span>,
]
</code></pre>
<p>In urls.py:</p>
<pre><code class="lang-bash">import debug_toolbar
from django.urls import path, include

urlpatterns = [
    ...
    path(<span class="hljs-string">"__debug__/"</span>, include(debug_toolbar.urls)),
]
</code></pre>
<p>When you load an endpoint in the browser during development, the toolbar displays total SQL queries, execution time, and duplicate queries. This makes inefficiencies immediately visible.</p>
<p>When you load an API endpoint and see 150 SQL queries for a single request, that’s a strong signal that something is wrong, often an N+1 query problem or inefficient serializer behavior.</p>
<h3 id="heading-logging-sql-queries">Logging SQL Queries</h3>
<p>Django allows you to log all executed SQL queries. This is especially useful when debugging API views.</p>
<p>Seeing the raw SQL makes inefficiencies obvious, such as repeated <code>SELECT</code> statements for the same table.</p>
<h4 id="heading-how-to-enable-sql-query-logging">How to Enable SQL Query Logging</h4>
<p>You can configure Django to log all SQL queries in settings.py:</p>
<pre><code class="lang-bash">LOGGING = {
    <span class="hljs-string">"version"</span>: 1,
    <span class="hljs-string">"handlers"</span>: {
        <span class="hljs-string">"console"</span>: {
            <span class="hljs-string">"class"</span>: <span class="hljs-string">"logging.StreamHandler"</span>,
        },
    },
    <span class="hljs-string">"loggers"</span>: {
        <span class="hljs-string">"django.db.backends"</span>: {
            <span class="hljs-string">"handlers"</span>: [<span class="hljs-string">"console"</span>],
            <span class="hljs-string">"level"</span>: <span class="hljs-string">"DEBUG"</span>,
        },
    },
}
</code></pre>
<p>With this configuration, every SQL query will be printed to the console when your API runs. Repeated SELECT statements or unexpected queries become obvious.</p>
<h3 id="heading-profiling-api-response-time">Profiling API Response Time</h3>
<p>Database queries are only one part of API performance. Beyond queries, it’s also important to measure the total response time of an endpoint.</p>
<p>Profiling response time helps you understand whether delays are caused by database access or by other parts of the request lifecycle. For example, if an endpoint takes 1.2 seconds to respond but only 50 milliseconds are spent on database queries, the bottleneck is likely in serialization, business logic, or repeated computations in Python.</p>
<p>By comparing query time and total response time, profiling helps you identify what to fix first instead of optimizing the wrong layer of the system.</p>
<h4 id="heading-how-to-measure-total-response-time">How to Measure Total Response Time</h4>
<pre><code class="lang-bash">import time
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view([<span class="hljs-string">"GET"</span>])
def example_view(request):
    start_time = time.time()

    <span class="hljs-comment"># Simulate work</span>
    data = {<span class="hljs-string">"message"</span>: <span class="hljs-string">"Hello world"</span>}

    response = Response(data)

    end_time = time.time()
    <span class="hljs-built_in">print</span>(f<span class="hljs-string">"Response time: {end_time - start_time:.4f} seconds"</span>)

    <span class="hljs-built_in">return</span> response
</code></pre>
<p>If database queries are fast but the total response time is high, the bottleneck may be serialization or expensive Python logic.  </p>
<p>Once you’ve identified that database access is a significant contributor to slow response times, the next step is to look more closely at how Django retrieves related data.</p>
<h3 id="heading-sql-query-optimization-in-django-rest-apis">SQL Query Optimization in Django REST APIs</h3>
<p>One of the most common reasons Django REST APIs become slow is inefficient access to related objects. This often manifests as the N+1 query problem, where fetching related objects triggers a separate database query for each item. Identifying and fixing this problem can significantly reduce the number of queries and improve API performance.</p>
<h4 id="heading-understanding-the-n1-query-problem">Understanding the N+1 Query Problem</h4>
<p>Consider a simple example:</p>
<ul>
<li><p>You fetch a list of posts</p>
</li>
<li><p>Each post has an author</p>
</li>
<li><p>For every post, Django fetches the author separately</p>
</li>
</ul>
<p>If you have 100 posts, this results in 101 queries: 1 for the posts and 100 for the authors. This happens because Django lazily loads related objects by default. Without intervention, your API performs repetitive database work that slows down response times.</p>
<h4 id="heading-solving-the-problem-with-selectrelated-and-prefetchrelated">Solving the Problem with <code>select_related</code> and <code>prefetch_related</code></h4>
<p>Django provides built-in tools to control how related objects are loaded efficiently: <code>select_related</code> and <code>prefetch_related</code>.</p>
<p><strong>1. Using</strong> <code>select_related</code></p>
<p><code>select_related</code> is designed for foreign key and one-to-one relationships. It performs an SQL join and retrieves related objects in a single query.</p>
<p>Use it when:</p>
<ul>
<li><p>You know you will access related objects</p>
</li>
<li><p>The relationship is one-to-one or many-to-one</p>
</li>
</ul>
<pre><code class="lang-bash">posts = Post.objects.select_related(<span class="hljs-string">"author"</span>)

<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-built_in">print</span>(post.author.name)  <span class="hljs-comment"># No additional queries</span>
</code></pre>
<p>This performs a SQL JOIN and retrieves posts and authors in a single query, eliminating the N+1 problem.</p>
<p>It reduces multiple queries into just one, avoiding repeated database hits.</p>
<p><strong>2. Using</strong> <code>prefetch_related</code></p>
<p><code>prefetch_related</code> is used for many-to-many and reverse foreign key relationships. It performs separate queries for each related table but combines the results in Python.</p>
<p>Use it when:</p>
<ul>
<li><p>A SQL join would produce too much duplicated data</p>
</li>
<li><p>You are dealing with collections of related objects</p>
</li>
</ul>
<h4 id="heading-example-how-to-optimize-a-many-to-many-relationship">Example: How to Optimize a Many-to-Many Relationship</h4>
<p>Consider a blog application where posts can have multiple tags:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># models.py</span>
class Tag(models.Model):
    name = models.CharField(max_length=50)

class Post(models.Model):
    title = models.CharField(max_length=200)
    tags = models.ManyToManyField(Tag)
</code></pre>
<p>Now imagine fetching posts and accessing their tags:</p>
<pre><code class="lang-bash">posts = Post.objects.all()

<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-built_in">print</span>(post.tags.all())  <span class="hljs-comment"># Triggers additional queries</span>
</code></pre>
<p>If you have 100 posts, Django may execute:</p>
<ul>
<li><p>1 query to fetch posts</p>
</li>
<li><p>1 query per post to fetch related tags</p>
</li>
</ul>
<p>This results in many unnecessary database hits.</p>
<p>You can optimize this using <code>prefetch_related</code>:</p>
<pre><code class="lang-bash">posts = Post.objects.prefetch_related(<span class="hljs-string">"tags"</span>)

<span class="hljs-keyword">for</span> post <span class="hljs-keyword">in</span> posts:
    <span class="hljs-built_in">print</span>(post.tags.all())  <span class="hljs-comment"># Uses prefetched data</span>
</code></pre>
<p>With this approach, Django performs one query for posts and one query for all related tags. It then matches them in Python, eliminating repeated database queries.</p>
<p>Together, these tools allow you to optimize your queries and eliminate the N+1 problem efficiently.</p>
<h4 id="heading-common-beginner-mistakes">Common Beginner Mistakes</h4>
<p>Even after applying these optimizations, it’s easy to make mistakes. Watch out for:</p>
<ul>
<li><p>Forgetting that serializers can trigger additional queries</p>
</li>
<li><p>Using <code>select_related</code> on many-to-many relationships</p>
</li>
<li><p>Assuming Django automatically optimizes queries</p>
</li>
<li><p>Not checking the query count after adding serializers</p>
</li>
</ul>
<p>Paying attention to these pitfalls ensures your API remains fast and scalable.</p>
<h3 id="heading-caching-in-django-rest-apis">Caching in Django REST APIs</h3>
<p>Even after optimizing database queries, API performance can still suffer if the same computations or database lookups are performed repeatedly. This is where caching comes in. Caching is a technique for storing the results of expensive operations so they can be retrieved more quickly the next time they are needed.</p>
<p>At its core, caching exists because computers have multiple layers of memory with different speeds:</p>
<ul>
<li><p>CPU registers (fastest)</p>
</li>
<li><p>L1, L2, L3 caches</p>
</li>
<li><p>Main memory (RAM)</p>
</li>
<li><p>SSD storage</p>
</li>
<li><p>HDD storage (slowest)</p>
</li>
</ul>
<p>Each layer trades speed for size: the closer the data is to the CPU, the faster it can be accessed. Software systems use the same principle; by storing frequently accessed data in a “closer” or faster location, applications can respond more quickly.</p>
<h4 id="heading-cache-eviction">Cache Eviction</h4>
<p>Caches are limited in size, so when a cache is full, some data must be removed to make room for new data. This process is called cache eviction.</p>
<p>Common eviction strategies include:</p>
<ul>
<li><p><strong>Least Recently Used (LRU):</strong> removes the data that hasn’t been accessed for the longest time</p>
</li>
<li><p><strong>Random Replacement:</strong> removes a random item from the cache</p>
</li>
</ul>
<p>The goal is to keep the data that is most likely to be requested again while freeing space for new data. Understanding this helps developers use caching effectively.</p>
<h4 id="heading-caching-in-application-architectures">Caching in Application Architectures</h4>
<p>Caching exists at several levels in modern software systems:</p>
<ul>
<li><p><strong>Client-side caching:</strong> Web browsers cache HTTP responses to reduce the need for repeated network requests. This is controlled with HTTP headers like <code>Cache-Control</code>.</p>
</li>
<li><p><strong>CDN caching:</strong> Content Delivery Networks store static assets closer to users, reducing latency and server load.</p>
</li>
<li><p><strong>Backend caching:</strong> Backend services cache results from database queries, computed values, or API responses. This is where Django caching is most commonly applied.</p>
</li>
</ul>
<p>By applying caching strategically at the backend, APIs can serve data faster while reducing computation and database load.</p>
<h4 id="heading-caching-in-django">Caching in Django</h4>
<p>Django provides a flexible caching framework that supports multiple backends, including in-memory, file-based, database-backed, and third-party stores like Redis. The main types of caching in Django are:</p>
<ol>
<li><p><strong>Per-view caching:</strong> caches the entire output of a view. Ideal for endpoints where responses rarely change.</p>
<pre><code class="lang-python"> <span class="hljs-keyword">from</span> django.views.decorators.cache <span class="hljs-keyword">import</span> cache_page

<span class="hljs-meta"> @cache_page(60 * 15)  # cache for 15 minutes</span>
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_view</span>(<span class="hljs-params">request</span>):</span>
</code></pre>
<ol start="2">
<li><p>Template fragment caching: caches specific parts of a template to avoid repeated rendering.</p>
</li>
<li><p>Low-level caching: gives full control over what is cached and for how long, making it ideal for API responses.</p>
</li>
</ol>
</li>
</ol>
<p>    By combining these approaches, you can reduce repeated work in your API, lower database load, and speed up response times.</p>
<h3 id="heading-when-to-use-redis">When to Use Redis</h3>
<p>While Django’s built-in caching backends are sufficient for many projects, high-traffic APIs often require a shared, in-memory cache. This is where Redis excels. Redis is designed for fast access, low latency, and can handle frequent reads across multiple servers.</p>
<p>You should consider using Redis when:</p>
<ul>
<li><p>Data is read frequently but changes infrequently</p>
</li>
<li><p>Low latency is important for API responses</p>
</li>
<li><p>You need cache expiration and eviction policies</p>
</li>
<li><p>You want a shared cache across multiple servers or services</p>
</li>
</ul>
<p>Redis is particularly effective for API endpoints that serve the same data to many users, such as frequently accessed lists or computed results.</p>
<h3 id="heading-common-beginner-mistakes-1">Common Beginner Mistakes</h3>
<p>Caching is powerful, but it’s easy to misuse. Some common pitfalls include:</p>
<ul>
<li><p><strong>Caching everything blindly:</strong> not all data benefits from caching</p>
</li>
<li><p><strong>Forgetting cache invalidation:</strong> stale data can lead to incorrect responses</p>
</li>
<li><p><strong>Using cache where query optimization would suffice:</strong> sometimes optimizing database queries is a better solution than caching.</p>
</li>
</ul>
<p>Remember: caching should complement good database design, not replace it.</p>
<h3 id="heading-pagination-and-limiting-expensive-datasets">Pagination and Limiting Expensive Datasets</h3>
<p>Even with caching, returning large datasets in a single request can slow down your API and increase memory usage. Pagination is a simple and effective way to limit the amount of data returned at once.</p>
<p>Pagination helps by reducing:</p>
<ul>
<li><p>Database load</p>
</li>
<li><p>Memory usage</p>
</li>
<li><p>Serialization time</p>
</li>
<li><p>Network transfer size</p>
</li>
</ul>
<p>Django REST Framework provides built-in pagination classes that make it easy to paginate endpoints. As a rule of thumb, always paginate list endpoints unless there is a strong reason not to.</p>
<h3 id="heading-load-testing-and-measuring-improvement">Load Testing and Measuring Improvement</h3>
<p>Optimizations are only meaningful if you can measure their impact. Load testing simulates multiple users accessing your API simultaneously, helping you answer key questions:</p>
<ul>
<li><p>How many requests per second can my API handle?</p>
</li>
<li><p>Where does the API start to break under load?</p>
</li>
<li><p>Did caching, query optimization, and pagination actually improve performance?</p>
</li>
</ul>
<p>By running load tests before and after optimization, you can validate that your changes have the desired effect and avoid optimizing the wrong parts of your system.</p>
<h2 id="heading-summary-and-next-steps">Summary and Next Steps</h2>
<p>Optimizing Django REST APIs isn’t about chasing every tiny micro-optimization. It’s about reducing unnecessary work and focusing on the parts of your API that actually slow down performance.</p>
<h4 id="heading-key-takeaways">Key Takeaways</h4>
<ul>
<li><p><strong>Profile before optimizing:</strong> Identify the real bottlenecks before making changes.</p>
</li>
<li><p><strong>Reduce database queries:</strong> Use techniques like <code>select_related</code>, <code>prefetch_related</code>, and avoid N+1 queries.</p>
</li>
<li><p><strong>Cache frequently accessed data:</strong> Use Django caching and Redis to reduce repeated computations.</p>
</li>
<li><p><strong>Paginate large datasets:</strong> Limit memory usage and network load by returning data in chunks.</p>
</li>
<li><p><strong>Measure performance changes:</strong> Always verify that your optimizations have a real impact.</p>
</li>
</ul>
<h4 id="heading-next-steps-for-your-apis">Next Steps for Your APIs</h4>
<ol>
<li><p><strong>Add profiling to your existing APIs</strong> to understand where time is spent.</p>
</li>
<li><p><strong>Identify one slow endpoint</strong> and focus on optimizing it first.</p>
</li>
<li><p><strong>Optimize database queries</strong> using Django ORM best practices.</p>
</li>
<li><p><strong>Introduce caching carefully</strong>; avoid caching everything blindly.</p>
</li>
<li><p><strong>Measure the results</strong> with load testing and performance metrics.</p>
</li>
</ol>
<p>Remember: Performance optimization is not a one-time task. It’s a habit built by continuously observing how your system works, testing improvements, and applying changes where they make the most impact.</p>
<h2 id="heading-read-more">Read More</h2>
<ol>
<li><p><a target="_blank" href="https://www.django-rest-framework.org/topics/performance/">DRF Performance</a></p>
</li>
<li><p><a target="_blank" href="https://docs.djangoproject.com/en/stable/topics/db/optimization/">Django ORM Optimization</a></p>
</li>
<li><p><a target="_blank" href="https://docs.djangoproject.com/en/stable/topics/db/optimization/#select-related">Understanding N+1 queries</a></p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use the Django REST Framework - Build Backend APIs with DRF ]]>
                </title>
                <description>
                    <![CDATA[ When you click on most backend development tutorials, they often teach you what to do, not how to think.That’s why many developers only realize their mistakes after they start building. So, how does one actually think like a backend developer? Before... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-the-django-rest-framework/</link>
                <guid isPermaLink="false">6920d5f802099ac646b401c5</guid>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mari ]]>
                </dc:creator>
                <pubDate>Fri, 21 Nov 2025 21:13:28 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763759552021/cc57d91b-c2b9-4a40-8bb9-52c517dbbc35.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you click on most backend development tutorials, they often teach you <em>what</em> to do, not <em>how to think</em>.<br>That’s why many developers only realize their mistakes after they start building.</p>
<p>So, how does one actually think like a backend developer? Before answering that, let’s start with the basics: what exactly is backend development?</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-backend-development">What is Backend Development?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-django-rest-framework">Why Django REST Framework?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-flask">Flask</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-fastapi">FastAPI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-django-rest-framework">Django REST Framework</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-think-like-a-backend-developer">How to Think Like a Backend Developer</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-think-in-systems-not-lines-of-code">1. Think in Systems, Not Lines of Code</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-separate-concerns-keep-things-organized">2. Separate Concerns — Keep Things Organized</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-anticipate-problems-before-they-happen">3. Anticipate Problems Before They Happen</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-4-make-your-code-predictable-and-readable">4. Make Your Code Predictable and Readable</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-5-think-in-the-request-logic-response-cycle">5. Think in the Request → Logic → Response Cycle</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-6-practice-thinking-like-a-backend-developer">6. Practice Thinking Like a Backend Developer</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-the-django-rest-framework">How to Install the Django REST Framework</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-install-python">Step 1: Install Python</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-create-a-project-folder">Step 2: Create a Project Folder</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-create-a-virtual-environment">Step 3: Create a Virtual Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-4-install-django">Step 4: Install Django</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-create-a-django-project">Step 5: Create a Django Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-6-install-django-rest-framework">Step 6: Install Django REST Framework</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-7-add-drf-to-installed-apps">Step 7: Add DRF to Installed Apps</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-8-run-initial-migrations">Step 8: Run Initial Migrations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-9-start-the-server">Step 9: Start the Server</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-10-verify-drf-installation">Step 10: Verify DRF Installation</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-the-backend-developers-mindset">The Backend Developer’s Mindset</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-mistakes-beginners-make">Common Mistakes Beginners Make</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-further-reading">Further Reading</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-backend-development">What is Backend Development?</h2>
<p>Backend development is the foundation of most web and mobile applications. It focuses on everything that happens behind the scenes, from processing logic and handling data to connecting with databases and APIs.</p>
<p>While it’s true that backend developers build APIs that communicate with the frontend, the job goes far beyond that. The backend is where data is validated, protected, stored, and retrieved.</p>
<p>In short: backend development is about building systems that ensure data integrity, performance, and scalability.</p>
<p>Backend developers are the ones responsible for designing and maintaining those systems. They ensure that every user request is processed efficiently and securely.</p>
<p>Now, how does the Django REST Framework (DRF) fit into all this?</p>
<h2 id="heading-why-django-rest-framework">Why Django REST Framework?</h2>
<p>A beginner-friendly tutorial must use a tool that:</p>
<ul>
<li><p>Teaches good structure</p>
</li>
<li><p>Encourages best practices</p>
</li>
<li><p>Hides unnecessary complexity</p>
</li>
<li><p>Helps you learn backend fundamentals correctly</p>
</li>
</ul>
<p>That’s why this guide uses the <strong>Django REST Framework (DRF)</strong>. Here’s how it compares to other popular Python frameworks.</p>
<h3 id="heading-flask">Flask</h3>
<p>Flask is a lightweight and flexible microframework. It is great for small projects, but:</p>
<ul>
<li><p>You have to set up everything manually (routing, JSON handling, database handling).</p>
</li>
<li><p>You need extra libraries for authentication, validation, or serialization.</p>
</li>
<li><p>Beginners often create unstructured projects because Flask doesn’t enforce architecture.</p>
</li>
</ul>
<p>Flask teaches freedom, not structure.</p>
<h3 id="heading-fastapi">FastAPI</h3>
<p>FastAPI is modern, fast, and async-first. However:</p>
<ul>
<li><p>It assumes you already understand APIs.</p>
</li>
<li><p>It requires understanding Python type hints deeply.</p>
</li>
<li><p>The ecosystem is still growing.</p>
</li>
<li><p>Beginners may not understand its underlying concepts (dependency injection, async IO).</p>
</li>
</ul>
<p>FastAPI teaches speed, not fundamentals.</p>
<h3 id="heading-django-rest-framework">Django REST Framework</h3>
<p>DRF is ideal for beginners because:</p>
<ul>
<li><p>It sits on top of Django, a very stable full-stack framework.</p>
</li>
<li><p>It encourages good architecture from day one.</p>
</li>
<li><p>It handles serialization, authentication, routing, validation, and permissions for you.</p>
</li>
<li><p>It gives you structure instead of chaos.</p>
</li>
</ul>
<p><strong>Bottom line:</strong> DRF can help you learn how backend systems work from scratch.</p>
<h2 id="heading-how-to-think-like-a-backend-developer">How to Think Like a Backend Developer</h2>
<p>Thinking like a backend developer is not about memorizing code. It’s about learning to see the bigger picture, how data moves, how logic flows, and how to build systems that work reliably and can grow.</p>
<p>Backend thinking can be summarized into six main principles:</p>
<h3 id="heading-1-think-in-systems-not-lines-of-code">1. Think in Systems, Not Lines of Code</h3>
<p>Many beginners focus on writing code that works for one feature. A backend developer thinks about the entire system.</p>
<p><strong>Analogy:</strong> Imagine a factory. Each machine (function or endpoint) does one task, but the factory only works efficiently if every machine is arranged correctly and communicates properly.</p>
<p><strong>Example:</strong> When a user submits a form to create a task:</p>
<ul>
<li><p>The request reaches the server.</p>
</li>
<li><p>The backend validates the data.</p>
</li>
<li><p>The backend stores it in the database.</p>
</li>
<li><p>The backend sends a response to the user.</p>
</li>
</ul>
<p>A backend developer doesn’t just write a function to save data. They ask:</p>
<ul>
<li><p>Where should this logic live — view, serializer, or service layer?</p>
</li>
<li><p>How will the data be validated and cleaned?</p>
</li>
<li><p>How will the system scale if thousands of users submit tasks at the same time?</p>
</li>
</ul>
<p>Seeing the system first makes code predictable, maintainable, and scalable.</p>
<h3 id="heading-2-separate-concerns-keep-things-organized">2. Separate Concerns — Keep Things Organized</h3>
<p>Backend thinking is about <strong>structure</strong>. Every piece of code should have a clear responsibility:</p>
<ul>
<li><p><strong>Models</strong>: Store and define your data</p>
</li>
<li><p><strong>Serializers</strong>: Convert data to a format the client understands (like JSON)</p>
</li>
<li><p><strong>Views</strong>: Apply the business logic and respond to requests</p>
</li>
</ul>
<p><strong>Why this matters:</strong> Without separation, code becomes messy and hard to debug. You might find yourself mixing database queries with validation or formatting, which leads to errors later.</p>
<p><strong>Simple analogy:</strong> Think of a restaurant.</p>
<ul>
<li><p>The <strong>chef</strong> prepares the food (model/data).</p>
</li>
<li><p>The <strong>waiter</strong> delivers the food to customers in a presentable way (serializer).</p>
</li>
<li><p>The <strong>manager</strong> decides who gets what and handles special requests (view/logic).</p>
</li>
</ul>
<p>Each role is separate but connected. This is exactly how backend developers structure code.</p>
<h3 id="heading-3-anticipate-problems-before-they-happen">3. Anticipate Problems Before They Happen</h3>
<p>Backend developers don’t just code for today. They <strong>think ahead</strong>:</p>
<ul>
<li><p>What if the user sends invalid data?</p>
</li>
<li><p>What if two users try to edit the same record at the same time?</p>
</li>
<li><p>How will the system handle millions of requests in the future?</p>
</li>
</ul>
<p><strong>Example:</strong> If a user tries to create a task without a title, a beginner might just let it crash. A backend developer writes validation rules to catch this and return a clear error message.</p>
<p><strong>Rule of thumb:</strong> Always ask, <em>“What could go wrong here?”</em> and design your code to handle it gracefully.</p>
<h3 id="heading-4-make-your-code-predictable-and-readable">4. Make Your Code Predictable and Readable</h3>
<p>Backend development is about <strong>writing code for humans, not just computers</strong>.</p>
<ul>
<li><p>Use clear variable names (<code>task_title</code> instead of <code>x</code>).</p>
</li>
<li><p>Keep functions short and focused.</p>
</li>
<li><p>Document your code.</p>
</li>
</ul>
<p>This way, <strong>anyone can pick up your code and understand it</strong>, including your future self.</p>
<p><strong>Tip:</strong> A backend system that is easy to read and predict is easier to debug, extend, and scale.</p>
<h3 id="heading-5-think-in-the-request-logic-response-cycle">5. Think in the Request → Logic → Response Cycle</h3>
<p>Every backend action fits into this pattern:</p>
<ul>
<li><p><strong>Request</strong>: The client sends data.</p>
</li>
<li><p><strong>Logic</strong>: The server validates, processes, and decides what to do.</p>
</li>
<li><p><strong>Response</strong>: The server sends data back in a structured way.</p>
</li>
</ul>
<p><strong>Example:</strong> User creates a task:</p>
<ul>
<li><p>Request: <code>{ "title": "Learn DRF" }</code></p>
</li>
<li><p>Logic: Check title is not empty → save to database → mark completed as <code>False</code></p>
</li>
<li><p>Response: <code>{ "id": 1, "title": "Learn DRF", "completed": false }</code></p>
</li>
</ul>
<p>Thinking in this cycle makes debugging and designing systems intuitive.</p>
<h3 id="heading-6-practice-thinking-like-a-backend-developer">6. Practice Thinking Like a Backend Developer</h3>
<ul>
<li><p><strong>Ask questions before coding:</strong> “Where should this logic live? How will this affect other parts of the system?”</p>
</li>
<li><p><strong>Break down problems into steps:</strong> Don’t just code the solution; code the process.</p>
</li>
<li><p><strong>Visualize data flow:</strong> Draw diagrams if necessary, from user request to database and back.</p>
</li>
<li><p><strong>Learn by doing:</strong> Build small projects and reflect on each component’s role.</p>
</li>
</ul>
<p>Check out Andy Harris’s video on how to think like a programmer.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/azcrPFhaY9k" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>Now that you understand how backend developers think, let’s walk through setting up a real backend environment using Django REST Framework.</p>
<h2 id="heading-how-to-install-the-django-rest-framework">How to Install the Django REST Framework</h2>
<p>Here’s how to get the Django REST framework running on your machine from scratch.</p>
<h3 id="heading-step-1-install-python">Step 1: Install Python</h3>
<p>Make sure you have <strong>Python 3.8+</strong> installed. You can check if Python is installed with this command:</p>
<pre><code class="lang-bash">python --version
</code></pre>
<p>If it’s not installed, download it from the <a target="_blank" href="https://docs.python.org/3/">official Python documentation</a>.</p>
<h3 id="heading-step-2-create-a-project-folder">Step 2: Create a Project Folder</h3>
<p>Choose a location on your computer and create a folder for your project:</p>
<pre><code class="lang-bash">mkdir my_drf_project
<span class="hljs-built_in">cd</span> my_drf_project
</code></pre>
<p>This keeps all your files organized in one place.</p>
<h3 id="heading-step-3-create-a-virtual-environment">Step 3: Create a Virtual Environment</h3>
<p>A virtual environment keeps your project dependencies separate from other projects.</p>
<p>Create a virtual environment:</p>
<pre><code class="lang-bash">python -m venv venv
</code></pre>
<p>Next, activate it. For Windows (PowerShell):</p>
<pre><code class="lang-powershell">.\venv\Scripts\Activate.ps1
</code></pre>
<p>For Mac/Linux:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> venv/bin/activate
</code></pre>
<p>You’ll know it’s active when your terminal prompt starts with <code>(venv)</code>.</p>
<h3 id="heading-step-4-install-django">Step 4: Install Django</h3>
<p>Now install Django inside the virtual environment:</p>
<pre><code class="lang-bash">pip install django
</code></pre>
<p>Check that Django is installed:</p>
<pre><code class="lang-bash">python -m django --version
</code></pre>
<h3 id="heading-step-5-create-a-django-project">Step 5: Create a Django Project</h3>
<p>Create a new Django project:</p>
<pre><code class="lang-bash">django-admin startproject core .
</code></pre>
<p>The <code>.</code> at the end means “create the project here.” Run the server to make sure it works:</p>
<pre><code class="lang-bash">python manage.py runserver
</code></pre>
<p>Visit <a target="_blank" href="http://127.0.0.1:8000/"><code>http://127.0.0.1:8000/</code></a> in your browser. You should see the Django welcome page.</p>
<h3 id="heading-step-6-install-django-rest-framework">Step 6: Install Django REST Framework</h3>
<p>Install DRF using pip:</p>
<pre><code class="lang-bash">pip install djangorestframework
</code></pre>
<h3 id="heading-step-7-add-drf-to-installed-apps">Step 7: Add DRF to Installed Apps</h3>
<p>Open <code>core/</code><a target="_blank" href="http://settings.py"><code>settings.py</code></a> and find the <code>INSTALLED_APPS</code> list. Add:</p>
<pre><code class="lang-bash"><span class="hljs-string">'rest_framework'</span>,
</code></pre>
<p>It should look like this:</p>
<pre><code class="lang-bash">INSTALLED_APPS = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'rest_framework'</span>,
]
</code></pre>
<h3 id="heading-step-8-run-initial-migrations">Step 8: Run Initial Migrations</h3>
<p>Set up your database:</p>
<pre><code class="lang-bash">python manage.py migrate
</code></pre>
<p>Create a superuser for accessing the admin panel:</p>
<pre><code class="lang-bash">python manage.py createsuperuser
</code></pre>
<p>Follow the prompts for username, email, and password.</p>
<h3 id="heading-step-9-start-the-server">Step 9: Start the Server</h3>
<p>Run your development server again:</p>
<pre><code class="lang-bash">python manage.py runserver
</code></pre>
<p>Visit:</p>
<ul>
<li><p><a target="_blank" href="http://127.0.0.1:8000/"><code>http://127.0.0.1:8000/</code></a> → Django welcome page</p>
</li>
<li><p><a target="_blank" href="http://127.0.0.1:8000/admin/"><code>http://127.0.0.1:8000/admin/</code></a> → Admin panel (login with superuser)</p>
</li>
</ul>
<p>You now have Django + DRF installed and ready for API development.</p>
<h3 id="heading-step-10-verify-drf-installation">Step 10: Verify DRF Installation</h3>
<p>The easiest way to confirm that Django REST Framework is installed correctly is to build a very small test API. Each part of the setup helps you verify that DRF is working end-to-end.</p>
<p>Create a new app:</p>
<pre><code class="lang-bash">python manage.py startapp api
</code></pre>
<p>This creates an <code>api</code> folder where you’ll place your test model, serializer, and view. Adding it to <code>INSTALLED_APPS</code> tells Django to recognize the new app.</p>
<p>Add it to <code>INSTALLED_APPS</code>:</p>
<pre><code class="lang-bash"><span class="hljs-string">'api'</span>,
</code></pre>
<p>Create a simple <a target="_blank" href="http://models.py"><code>models.py</code></a> in the <code>api</code> app:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Task</span>(<span class="hljs-params">models.Model</span>):</span>
    title = models.CharField(max_length=<span class="hljs-number">200</span>)
    completed = models.BooleanField(default=<span class="hljs-literal">False</span>)
</code></pre>
<p>This model represents a basic task with a title and a completion status. Creating even a simple model lets you test whether DRF can serialize and expose database objects as API responses.</p>
<p>Run migrations:</p>
<pre><code class="lang-bash">python manage.py makemigrations
python manage.py migrate
</code></pre>
<p>These commands generate and apply database tables for the <code>Task</code> model. Without migrations, DRF won’t have anything to fetch and serialize.</p>
<p>Create a serializer (<code>api/</code><a target="_blank" href="http://serializers.py"><code>serializers.py</code></a>):</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> rest_framework <span class="hljs-keyword">import</span> serializers
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Task

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskSerializer</span>(<span class="hljs-params">serializers.ModelSerializer</span>):</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        model = Task
        fields = <span class="hljs-string">'__all__'</span>
</code></pre>
<p>A serializer converts your <code>Task</code> model into JSON so it can be returned as an API response. This step confirms that DRF’s serializer tools are working.</p>
<p>Create a view (<code>api/</code><a target="_blank" href="http://views.py"><code>views.py</code></a>):</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> rest_framework <span class="hljs-keyword">import</span> viewsets
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Task
<span class="hljs-keyword">from</span> .serializers <span class="hljs-keyword">import</span> TaskSerializer

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TaskViewSet</span>(<span class="hljs-params">viewsets.ModelViewSet</span>):</span>
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
</code></pre>
<p><code>ModelViewSet</code> automatically creates the CRUD API endpoints for your model. If this loads correctly, it means DRF’s generic views and viewsets are functioning.</p>
<p>Wire it to URLs (<code>core/</code><a target="_blank" href="http://urls.py"><code>urls.py</code></a>):</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path, include
<span class="hljs-keyword">from</span> rest_framework.routers <span class="hljs-keyword">import</span> DefaultRouter
<span class="hljs-keyword">from</span> api.views <span class="hljs-keyword">import</span> TaskViewSet

router = DefaultRouter()
router.register(<span class="hljs-string">'tasks'</span>, TaskViewSet)

urlpatterns = [
    path(<span class="hljs-string">'admin/'</span>, admin.site.urls),
    path(<span class="hljs-string">'api/'</span>, include(router.urls)),
]
</code></pre>
<p>The router generates routes <code>/api/tasks/</code> for you. If routing works, DRF is properly integrated into your Django project.</p>
<p>Test the API by visiting:</p>
<pre><code class="lang-bash">http://127.0.0.1:8000/api/tasks/
</code></pre>
<p>If everything is set up correctly, you’ll see Django REST Framework’s browsable API. This confirms that DRF is installed, your project recognizes it, and it can serialize and return data successfully.</p>
<h2 id="heading-the-backend-developers-mindset">The Backend Developer’s Mindset</h2>
<p>When writing backend code, your goal isn’t just to make something <em>work</em>; it’s to make it predictable, scalable, and maintainable.</p>
<p>Professional backend developers focus on:</p>
<ul>
<li><p><strong>Predictability over cleverness</strong> — Code should be clear to others.</p>
</li>
<li><p><strong>Separation of concerns</strong> — Keep logic, data, and presentation layers distinct.</p>
</li>
<li><p><strong>Validation</strong> — Never trust user input; always validate.</p>
</li>
<li><p><strong>Consistency</strong> — Stick to naming conventions and reusable patterns.</p>
</li>
</ul>
<p>This mindset is what separates backend <em>coders</em> from backend <em>engineers</em>.</p>
<h2 id="heading-common-mistakes-beginners-make">Common Mistakes Beginners Make</h2>
<ul>
<li><p><strong>Writing too much logic in views:</strong> Keep views light. Move business logic into services or serializers.</p>
</li>
<li><p><strong>Ignoring validation</strong>: Always define validation rules in your serializers.</p>
</li>
<li><p><strong>Not planning for scalability:</strong> Even small projects grow. Build like you expect more users.</p>
</li>
</ul>
<h2 id="heading-further-reading">Further Reading</h2>
<p><a target="_blank" href="https://docs.djangoproject.com/en/5.2/">Django official documentation</a></p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-a-rest-api-in-django/">How to Build a REST API in Django</a></p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/what-is-serialization/">What is Serialization?</a></p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/rest-api-best-practices-rest-endpoint-design-examples/">REST API Best Practices – REST Endpoint Design Examples</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Thinking like a backend developer isn’t about memorizing syntax; it’s about understanding how systems behave.</p>
<p>When you start reasoning through requests, logic, and responses, you begin to see the bigger picture, and that’s when you stop writing code and start building systems.</p>
<p>With Django REST Framework, that process becomes easier, cleaner, and more intuitive.</p>
<p>As you continue learning, build small APIs and gradually add features. The more you understand how data flows through a system, the more naturally backend thinking will come.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Get Started with PocketBase: Build a Lightweight Backend in Minutes ]]>
                </title>
                <description>
                    <![CDATA[ If you’re a developer looking for a simple, fast, and self-hosted backend, PocketBase might be exactly what you need. It’s an open-source backend written in Go that lets you set up a complete backend with database, authentication, file storage, and r... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-get-started-with-pocketbase-build-a-lightweight-backend-in-minutes/</link>
                <guid isPermaLink="false">691770eb5879bafaa784b694</guid>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ golang ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Go Language ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Fri, 14 Nov 2025 18:11:55 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763143867523/1a4c8cd4-629f-4dd7-8a82-5b6d0d34d90e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you’re a developer looking for a simple, fast, and self-hosted backend, <a target="_blank" href="https://github.com/pocketbase/pocketbase">PocketBase</a> might be exactly what you need.</p>
<p>It’s an open-source backend written in Go that lets you set up a complete backend with database, authentication, file storage, and real-time updates, all in a single executable file.</p>
<p>In this guide, we’ll explore what makes PocketBase special, how to set it up, and how you can deploy it to the cloud.</p>
<h2 id="heading-what-well-cover">What We’ll Cover:</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-pocketbase">What is PocketBase</a>?</p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-developers-love-pocketbase">Why Developers Love PocketBase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-install-pocketbase">How to Install Pocketbase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-extending-pocketbase-with-javascript">Extending PocketBase with JavaScript</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-sdks-to-interact-with-pocketbase">Using SDKs to Interact with PocketBase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-self-hosting-pocketbase-using-sevalla">Self-Hosting PocketBase using Sevalla</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-security-and-open-source-nature">Security and Open Source Nature</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-pocketbase">When to Use PocketBase</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-pocketbase">What is PocketBase?</h2>
<p>PocketBase is an all-in-one backend that provides everything you need to power a modern web or mobile app, eliminating the need for large infrastructure.</p>
<p>It includes an embedded <a target="_blank" href="https://sqlite.org/">SQLite</a> database, real-time subscriptions, file and user management, a clean admin dashboard, and a REST-style API.</p>
<p>Since it runs from a single file, you can deploy it almost anywhere, from a VPS to your local machine or even a Raspberry Pi.</p>
<p>It’s designed for developers who want control and simplicity at the same time. You don’t need to manage separate servers for authentication, storage, and API endpoints. PocketBase handles all of this out of the box. You can use it as a standalone backend or embed it in your Go application to create a custom solution.</p>
<h2 id="heading-why-developers-love-pocketbase">Why Developers Love PocketBase</h2>
<p><a target="_blank" href="https://pocketbase.io/docs/how-to-use/">PocketBase</a> focuses on speed and simplicity. You don’t need to install multiple packages or services.</p>
<p>Once downloaded, you can start it with a single command. Then it’ll launch a web-based admin dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762853066915/e2f3af60-0a75-4b76-b55f-613b67b3e783.png" alt="PocketBase dashboard" class="image--center mx-auto" width="1000" height="420" loading="lazy"></p>
<p>The database is built using SQLite, which means data is stored locally by default, but you can use extensions to connect it with your existing workflows or cloud storage.</p>
<p>Another major advantage is its real-time capabilities. Every change in the database can be broadcast instantly to connected clients through WebSocket subscriptions. This makes it perfect for building apps like chat systems, dashboards, and collaboration tools that require instant updates.</p>
<h2 id="heading-how-to-install-pocketbase">How to Install PocketBase</h2>
<p>Getting PocketBase running takes less than a minute. You can download a <a target="_blank" href="https://pocketbase.io/docs/">prebuilt executable</a> from the official releases page.</p>
<p>It supports all major platforms, including Windows, macOS, and Linux.</p>
<p>Once downloaded, extract the archive and navigate to the folder in your terminal. Run the following command:</p>
<pre><code class="lang-python">./pocketbase serve
</code></pre>
<p>This command starts a local server and launches the admin dashboard at <code>http://127.0.0.1:8090/_/</code>. From there, you can create collections, add users, upload files, and manage data. There’s no setup wizard or dependency installation – everything is self-contained inside that one binary.</p>
<p>If you’re a Go developer, you can also install PocketBase as a Go module and use it directly in your project to build custom logic or extend the existing API.</p>
<h3 id="heading-using-pocketbase-as-a-go-framework">Using PocketBase as a Go Framework</h3>
<p>PocketBase can act as a Go framework, letting you build your own backend logic while keeping everything in one file. Here’s a simple example that shows how you can extend it with a custom route.</p>
<pre><code class="lang-python">package main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"github.com/pocketbase/pocketbase"</span>
    <span class="hljs-string">"github.com/pocketbase/pocketbase/core"</span>
)
func main() {
    app := pocketbase.New()
    app.OnServe().BindFunc(func(se *core.ServeEvent) error {
        se.Router.GET(<span class="hljs-string">"/hello"</span>, func(re *core.RequestEvent) error {
            <span class="hljs-keyword">return</span> re.String(<span class="hljs-number">200</span>, <span class="hljs-string">"Hello world!"</span>)
        })
        <span class="hljs-keyword">return</span> se.Next()
    })
    <span class="hljs-keyword">if</span> err := app.Start(); err != nil {
        log.Fatal(err)
    }
}
</code></pre>
<p>Once the file is ready, run these commands:</p>
<pre><code class="lang-python">go mod init myapp &amp;&amp; go mod tidy
go run main.go serve
</code></pre>
<p>You’ll now have a working backend with both the PocketBase dashboard and your custom <code>/hello</code> endpoint available at the same time.</p>
<p>This makes PocketBase flexible, you can use it as a ready-to-run backend or as part of a more complex Go project.</p>
<h2 id="heading-extending-pocketbase-with-javascript">Extending PocketBase with JavaScript</h2>
<p>PocketBase includes a built-in JavaScript engine that lets you extend its behavior without modifying or recompiling the Go code. This makes it easy to add custom logic, validation, automation, and event-driven workflows directly inside your backend.</p>
<p>You can create JavaScript files inside the pb_hooks folder, and PocketBase will automatically load and run them. These scripts can listen to events like record creation, updates, authentication, and more.</p>
<p>Here’s a simple example that sends a welcome email whenever a new user signs up.</p>
<p>Create a file named pb_hooks/user_email.js inside your PocketBase directory:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">/// &lt;reference path="../pb_data/types.d.ts" /&gt;</span>

onRecordAfterCreate(<span class="hljs-string">"users"</span>, <span class="hljs-keyword">async</span> (e) =&gt; {
    <span class="hljs-keyword">const</span> user = e.record;

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"New user registered:"</span>, user.email);

    <span class="hljs-comment">// Example: send a welcome email using a third-party API</span>
    <span class="hljs-keyword">const</span> emailResponse = <span class="hljs-keyword">await</span> $http.send({
        <span class="hljs-attr">url</span>: <span class="hljs-string">"https://api.example.com/send-email"</span>,
        <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
        <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
            <span class="hljs-attr">to</span>: user.email,
            <span class="hljs-attr">subject</span>: <span class="hljs-string">"Welcome to our app!"</span>,
            <span class="hljs-attr">message</span>: <span class="hljs-string">`Hi <span class="hljs-subst">${user.username}</span>, thanks for signing up!`</span>
        }),
        <span class="hljs-attr">headers</span>: {
            <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>
        }
    });

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Email status:"</span>, emailResponse.status);
});
</code></pre>
<p>This script runs automatically whenever a new record is created in the users collection. It picks up the user’s email, logs it, and uses PocketBase’s built-in HTTP client ($http) to call an external email service.</p>
<p>You can use the same pattern to validate data before saving, trigger webhooks, block actions, or update related records. Since everything runs inside PocketBase, you don’t need extra servers or functions to automate backend logic.</p>
<p>This makes it friendly for teams who may not be comfortable with Go but still want to add dynamic logic to their backend. You can find more details in the official documentation under “<a target="_blank" href="https://pocketbase.io/docs/js-overview/">Extend with JavaScript</a>.”</p>
<h2 id="heading-using-sdks-to-interact-with-pocketbase">Using SDKs to Interact with PocketBase</h2>
<p>To make it easier to communicate with your backend, PocketBase provides official SDKs for JavaScript and Dart.</p>
<p>The JavaScript SDK works well for browser-based or Node.js projects, while the Dart SDK is ideal for mobile apps built with Flutter. Both SDKs provide an easy way to connect, authenticate users, and perform CRUD operations without manually writing HTTP requests.</p>
<p>For example, in JavaScript you can connect and fetch data like this:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> PocketBase <span class="hljs-keyword">from</span> <span class="hljs-string">'pocketbase'</span>

const pb = new PocketBase(<span class="hljs-string">'http://127.0.0.1:8090'</span>)
const records = <span class="hljs-keyword">await</span> pb.collection(<span class="hljs-string">'posts'</span>).getList(<span class="hljs-number">1</span>, <span class="hljs-number">20</span>)
console.log(records)
</code></pre>
<p>This simplicity allows you to focus on building your frontend while PocketBase handles authentication, database operations, and real-time updates.</p>
<h2 id="heading-self-hosting-pocketbase-using-sevalla">Self-Hosting PocketBase using Sevalla</h2>
<p>When you are ready to move beyond testing, PocketBase gives you two options. You can self-host it using your own infrastructure or use their managed cloud version at <a target="_blank" href="https://pocketbase.io/">Pocketbase.io</a>.</p>
<p>Self-hosting gives you full control and is usually preferred by technical teams who want to keep sensitive data in-house.</p>
<p>You can choose any cloud provider, like AWS, DigitalOcean, or others to set up Pocketbase. But I will be using Sevalla.</p>
<p><a target="_blank" href="https://sevalla.com/">Sevalla</a> is a PaaS provider designed for developers and dev teams shipping features and updates constantly in the most efficient way. It offers application hosting, database, object storage, and static site hosting for your projects.</p>
<p>I am using Sevalla for two reasons:</p>
<ul>
<li><p>Every platform will charge you for creating a cloud resource. Sevalla comes with a $50 credit for us to use, so we won’t incur any costs for this example.</p>
</li>
<li><p>Sevalla has a <a target="_blank" href="https://docs.sevalla.com/templates/overview">template for PocketBase</a>, so it simplifies the manual installation and setup for each resource you will need for installation.</p>
</li>
</ul>
<p><a target="_blank" href="https://app.sevalla.com/login">Log in</a> to Sevalla and click on Templates. You can see Pocketbaseas one of the templates.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762853103062/870636bf-11df-4e3d-a73a-ebc0664818c2.png" alt="Sevalla Templates" class="image--center mx-auto" width="1000" height="187" loading="lazy"></p>
<p>Click on the “PocketBase” template. You will see the resources needed to provision the application. Click on “Deploy Template”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762853130642/f8ec7556-6544-4826-8c85-105e3893ca0c.png" alt="Sevalla Deployment" class="image--center mx-auto" width="1000" height="374" loading="lazy"></p>
<p>You can see the resource being provisioned. Once the deployment is complete, go to the PocketBase application and click on “Visit app”</p>
<p>You will see a 404 message. Add <code>_</code> to the url and you will see the login dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762853157824/6399c01d-7ae1-4c06-9f1d-9d7951bf04f7.png" alt="Sevalla Deployment" class="image--center mx-auto" width="1000" height="374" loading="lazy"></p>
<p>To login for the first time, you will need a superuser login. To create that, go back to the application and click “Logs”. You will see a url starting with <a target="_blank" href="http://0.0.0.0.">https://0.0.0.0.</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762853191932/d217e02f-91e8-4d28-ad4f-7eeb8d44b113.png" alt="Pocketbase Deployment" class="image--center mx-auto" width="1000" height="373" loading="lazy"></p>
<p>Replace the 0.0.0.0 with your new cloud URL and copy paste the full path into the browser. You will see the option to create a super user for your PocketBase deployment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762853227941/26c7086f-f95e-467a-a1db-97c34eadbcd4.png" alt="Pocketbase Create Super User" class="image--center mx-auto" width="1000" height="716" loading="lazy"></p>
<p>Once you have created the super user, you can again go to <code>/_</code> and login using the username and password. You should now see the PocketBase dashboard.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762853283532/8cfc48e4-383a-4e11-820e-d64d22ed937d.png" alt="Pocketbase Dashboard" class="image--center mx-auto" width="1000" height="421" loading="lazy"></p>
<p>You now have a production-grade Pocketbase server running on the cloud. You can use this to set up tables for your database and use the JavaScript or other SDKs to interact with Pocketbase.</p>
<h2 id="heading-security-and-open-source-nature">Security and Open Source Nature</h2>
<p>PocketBase is open source and licensed under MIT, which means you’re free to use it in personal or commercial projects. If you find a bug or security issue, you can report it to the maintainers, and they’ll address it promptly.</p>
<p>The project’s transparent development and active community make it a solid choice for startups, indie developers, and hobbyists who prefer to own their infrastructure.</p>
<p>Because it’s still in active development, backward compatibility isn’t guaranteed before version 1.0. But it’s already stable enough for small to medium-scale applications.</p>
<h2 id="heading-when-to-use-pocketbase">When to Use PocketBase</h2>
<p>PocketBase is perfect for projects that need a simple backend with low maintenance. It’s ideal for prototypes, small SaaS products, indie apps, internal tools, and educational projects.</p>
<p>Instead of setting up a complex stack with PostgreSQL, Node.js, and nginx, you can get your backend running instantly and focus on your product.</p>
<p>Suppose your project later grows into something bigger. In that case, you can migrate to a more complex setup or continue using PocketBase as a lightweight service for specific features like authentication or real-time data sync.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>PocketBase brings back the joy of fast development without complicated setups. With just one executable, you get a backend that supports authentication, real-time updates, file uploads, and an admin dashboard. It’s open source, fast, and customizable, making it a great choice for developers who want to move quickly without giving up control.</p>
<p>Whether you’re building a personal app, a startup MVP, or an internal dashboard, PocketBase gives you the power to set up a full backend in minutes. You can start small, extend it as needed, and deploy it anywhere  –  all while keeping your workflow simple and efficient.</p>
<p><em>Hope you enjoyed this article. Find me on</em> <a target="_blank" href="https://linkedin.com/in/manishmshiva"><em>Linkedin</em></a> <em>or</em> <a target="_blank" href="https://manishshivanandhan.com/"><em>visit my website</em></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement Dependency Injection in FastAPI ]]>
                </title>
                <description>
                    <![CDATA[ Several languages and frameworks depend on dependency injection—no pun intended. Go, Angular, NestJS, and Python's FastAPI all use it as a core pattern. If you've been working with FastAPI, you've likely encountered dependencies in action. Perhaps yo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-implement-dependency-injection-in-fastapi/</link>
                <guid isPermaLink="false">691740a91f4fa448325a55f9</guid>
                
                    <category>
                        <![CDATA[ dependency injection ]]>
                    </category>
                
                    <category>
                        <![CDATA[ FastAPI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nneoma Uche ]]>
                </dc:creator>
                <pubDate>Fri, 14 Nov 2025 14:46:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1763131442081/76eff35b-be68-49c1-9743-d78ebc87b292.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Several languages and frameworks depend on dependency injection—no pun intended. Go, Angular, NestJS, and Python's FastAPI all use it as a core pattern.</p>
<p>If you've been working with FastAPI, you've likely encountered dependencies in action. Perhaps you saw <code>Depends()</code> in a tutorial or the docs and were confused for a minute. I certainly was. That confusion sparked weeks of experimenting with this system. The truth is, you can't avoid dependency injection when building backend services with FastAPI. It's baked into the framework's DNA, powering everything from authentication and database connections to request validation.</p>
<p>FastAPI's docs describe its dependency injection system as 'powerful but intuitive.' That’s accurate, once you understand how it works. This article breaks it down, covering function dependencies, class dependencies, dependency scopes, as well as practical examples.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-dependencies-and-dependency-injection-in-fastapi">Dependencies and Dependency Injection in FastAPI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-getting-started-environment-setup">Getting Started: Environment Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-types-of-dependencies-in-fastapi">Types of Dependencies in FastAPI</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-use-function-dependencies-in-fastapi">How to Use Function Dependencies in FastAPI</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-class-dependencies-in-fastapi">How to Use Class Dependencies in FastAPI</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-dependency-scope">Dependency Scope</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-path-operation-level">Path Operation Level</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-router-level">Router Level</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-application-level">Application Level</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-common-use-cases-for-dependency-injection">Common Use Cases for Dependency Injection</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this article, you should have:</p>
<ul>
<li><p>Working knowledge of Python.</p>
</li>
<li><p>Ability to create and activate virtual environments.</p>
</li>
<li><p>Basic understanding of FastAPI.</p>
</li>
<li><p>Familiarity with Object-Oriented Programming (OOP) concepts.</p>
</li>
</ul>
<h2 id="heading-dependencies-and-dependency-injection-in-fastapi">Dependencies and Dependency Injection in FastAPI</h2>
<p>A dependency is a reusable piece of logic, like authentication, database connection, or validation, that your path operations require. Dependency injection (DI) is how FastAPI delivers these dependencies to specific parts of your application: you declare them using <code>Depends()</code> and FastAPI automatically executes them when the associated route receives a request.</p>
<p>Think of it as requesting the tools your application needs. You declare dependencies once and FastAPI provides them wherever needed, with no repetitive setup across routes.</p>
<p>This makes for modular, scalable applications. Without DI, you would have to repeat the same setup code on every endpoint, making updates tedious and bugs more likely.</p>
<h2 id="heading-getting-started-environment-setup">Getting Started: Environment Setup</h2>
<p>Let's set up your development environment to work through the examples in this guide.</p>
<p>Start by creating a project folder, then:</p>
<p>Create and activate a virtual environment:</p>
<pre><code class="lang-bash">python -m venv deps
<span class="hljs-built_in">source</span> deps/bin/activate          <span class="hljs-comment">#on Mac</span>
deps\Scripts\activate             <span class="hljs-comment"># On Windows</span>
</code></pre>
<p>Install FastAPI with all dependencies:</p>
<pre><code class="lang-python">pip install <span class="hljs-string">'fastapi[all]'</span>
</code></pre>
<p>Organize your project as follows:</p>
<pre><code class="lang-python">fastapi-deps/
├── deps/                 <span class="hljs-comment"># Virtual environment</span>
├── function_deps.py
├── class_deps.py
├── router_deps.py
├── app.py
└── requirements.txt
</code></pre>
<h2 id="heading-types-of-dependencies-in-fastapi">Types of Dependencies in FastAPI</h2>
<p>In FastAPI, a dependency is a callable object that retrieves or verifies information before a route executes. Dependencies can be implemented as either functions or classes.</p>
<p><strong>Function dependencies</strong> are the most straightforward approach and work well for most use cases, including validation, authentication, and data retrieval. <strong>Class dependencies</strong> can handle the same tasks but are particularly useful when you need stateful logic, multiple instances with different configurations, or prefer object-oriented patterns.</p>
<h3 id="heading-how-to-use-function-dependencies-in-fastapi">How to Use Function Dependencies in FastAPI</h3>
<p>A function dependency is a helper function (such as for authentication or data retrieval) that can be injected into path operations. To demonstrate, we'll create a simple user authentication dependency using an in-memory database—a list of dictionaries.</p>
<p>Recall the folder structure from earlier? We’ll write this code in <code>fastapi-deps/function_deps.py</code>.</p>
<p>Start by importing the required modules:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Depends, HTTPException
<span class="hljs-keyword">import</span> uvicorn
</code></pre>
<p>You bring in <code>FastAPI</code> to create the app instance, <code>Depends</code> for dependency injection, and <code>HTTPException</code> to handle errors gracefully. <code>uvicorn</code> will be used to run the application later.</p>
<p>Next, instantiate the FastAPI application:</p>
<pre><code class="lang-python">app = FastAPI()
</code></pre>
<p><code>app = FastAPI()</code> creates your application instance: the object that will hold all your endpoints and dependencies.</p>
<p>Next, create an in-memory database. Define a list of dictionaries to act as your temporary database. Each dictionary represents a user entry containing a name and a password.</p>
<pre><code class="lang-python">users = [
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Ore"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"jkzvdgwya12"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Uche"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"lga546"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Seke"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"SK99!"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Afi"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"Afi@144"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Sam"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"goTiger72*"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Ozi"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"xx%hI"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Ella"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"Opecluv18"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Claire"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"cBoss@14G"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Sena"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"SenDaBoss5"</span>},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Ify"</span>, <span class="hljs-string">"password"</span>: <span class="hljs-string">"184Norab"</span>}  
]
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">This type of database isn’t persistent; any data stored therein is lost when the application restarts.</div>
</div>

<p>Then, define a dependency function for user validation. The simple helper function below checks whether a username and password provided by the user match an existing user in the database.</p>
<pre><code class="lang-python"><span class="hljs-comment">#the dependency function</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_dep</span>(<span class="hljs-params">name: str, password: str</span>):</span>
    <span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> users:
        <span class="hljs-keyword">if</span> u[<span class="hljs-string">"name"</span>] == name <span class="hljs-keyword">and</span> u[<span class="hljs-string">"password"</span>] == password:
            <span class="hljs-keyword">return</span> {<span class="hljs-string">"name"</span>: name, <span class="hljs-string">"valid"</span>: <span class="hljs-literal">True</span>}
</code></pre>
<p>This function expects two string parameters, <code>name</code> and <code>password</code>, from the incoming request. If it finds a match in the <code>users</code> database, it returns a dictionary confirming the user’s validity. FastAPI automatically converts this dictionary into a JSON response.</p>
<p>Next, inject the dependency into a path function:</p>
<pre><code class="lang-python"><span class="hljs-comment">#the web endpoint</span>
<span class="hljs-meta">@app.get("/users/{user}")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>(<span class="hljs-params">user = Depends(<span class="hljs-params">user_dep</span>)</span>) -&gt; dict:</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> user:
        <span class="hljs-keyword">raise</span> HTTPException(status_code=<span class="hljs-number">401</span>, detail=<span class="hljs-string">"Invalid username or password"</span>)
    <span class="hljs-keyword">return</span> user
</code></pre>
<p>The <code>user_dep</code> function is injected into the path operation using <code>Depends()</code>. When an HTTP request is made to this endpoint, FastAPI executes the dependency first, validates the input, and passes its return value to the <code>user</code> parameter.</p>
<p>The <code>-&gt; dict:</code> annotation indicates that the function returns a dictionary, which FastAPI auto-converts to JSON. If no matching record is found, an <code>HTTPException</code> with a 401 status code is raised; otherwise, the verified user data is returned.</p>
<p>Now you’ll start the FastAPI server. To start the server, open your terminal in the project directory and run:</p>
<pre><code class="lang-python">uvicorn function_deps:app --reload
</code></pre>
<ul>
<li><p><code>function_deps</code> is the name of your Python file (without the <strong>.py</strong> extension).</p>
</li>
<li><p><code>--reload</code> automatically restarts the server whenever you save changes.</p>
</li>
</ul>
<p>Once it starts, you’ll see an output similar to the image below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762651145390/479b187c-f455-4617-aa7f-e075bf668ee5.jpeg" alt="uvicorn output in terminal" class="image--center mx-auto" width="597" height="37" loading="lazy"></p>
<p>Now you can test the endpoint. Open your browser or the Postman desktop app to validate the user <strong>“Seke”</strong>. Paste this URL into your browser: <em>http://127.0.0.1:8000/users/{user}?name=Seke&amp;password=SK99!</em></p>
<p>Alternatively, you can test the endpoint using FastAPI’s built-in docs at: http://127.0.0.1:8000/docs</p>
<p>In the Swagger UI:</p>
<ul>
<li><p>Click on the <strong>Get User</strong> endpoint</p>
</li>
<li><p>Click <strong>Try it out</strong></p>
</li>
<li><p>Enter “Seke” in the name field and “SK99!” in the password field</p>
</li>
<li><p>Click <strong>Execute</strong></p>
</li>
</ul>
<p>You should get a 200 status code, with the payload in this image:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762651845087/9495107e-1ab8-4349-a701-04e5de461fb6.jpeg" alt="payload for get_user endpoint" class="image--center mx-auto" width="402" height="246" loading="lazy"></p>
<p>You can also test the endpoint with usernames or passwords that don’t exist in the database. Each time, you should see a <strong>401</strong> error like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762652045213/c8dc8bb1-e2c4-456f-92f5-911dddae73eb.jpeg" alt="unauthorized error output in FastAPI docs" class="image--center mx-auto" width="417" height="197" loading="lazy"></p>
<h3 id="heading-how-to-use-class-dependencies-in-fastapi">How to Use Class Dependencies in FastAPI</h3>
<p>While functions are the most common way to define dependencies, FastAPI also supports class-based dependencies. Classes are useful when you need reusable instances with configurable state or prefer object-oriented patterns.</p>
<p>Class dependencies inject the same way: through the <code>Depends</code> function in your path operation.</p>
<p>Let's convert the <code>user_dep</code> function dependency to a class. It will authenticate users, grant access to valid credentials, and raise exceptions for unauthorized attempts. We'll apply it to a user dashboard endpoint to ensure only authenticated users access their resources.</p>
<pre><code class="lang-python"><span class="hljs-comment">#Dependency class for user authentication</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserAuth</span>():</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, name: str, password: str</span>):</span>
        self.name = name
        self.password = password

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__call__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-comment">#check if name and password entered correspond to any row in the db</span>
        <span class="hljs-keyword">for</span> user <span class="hljs-keyword">in</span> users:
            <span class="hljs-keyword">if</span> user[<span class="hljs-string">"name"</span>] == self.name <span class="hljs-keyword">and</span> user[<span class="hljs-string">"password"</span>] == self.password:
                <span class="hljs-keyword">pass</span>
        <span class="hljs-comment">#If no match found, raise an error</span>
        <span class="hljs-keyword">raise</span> HTTPException(status_code=<span class="hljs-number">401</span>, detail=<span class="hljs-string">"Invalid username or password"</span>)
</code></pre>
<p>The <code>__init</code>__ method receives the parameters from the request (<code>name</code> and <code>password</code>) and stores them as instance attributes. These can then be accessed in the <code>__call__</code> method, which contains the dependency logic.</p>
<p>Note that <code>__call__</code> doesn't return a value in this example. It simply raises an <code>HTTPException</code> if authentication fails. The <code>__call__</code> method makes the class instance callable, allowing FastAPI to invoke it like a regular function.</p>
<p>Here’s how to inject <code>UserAuth</code> into a path function:</p>
<pre><code class="lang-python"><span class="hljs-comment">#Injecting the class dependency into a path operation</span>
<span class="hljs-meta">@app.get("/user/dashboard")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_dashboard</span>(<span class="hljs-params">user: UserAuth = Depends(<span class="hljs-params">UserAuth</span>)</span>):</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span>: <span class="hljs-string">f"Access granted to <span class="hljs-subst">{user.name}</span>"</span>}
</code></pre>
<p><strong>What's happening here:</strong></p>
<p>When a client requests the <code>/user/dashboard</code> endpoint, FastAPI executes the dependency first. Recognizing <code>UserAuth</code> as a class, FastAPI automatically creates an instance and populates it with values from the query parameters.</p>
<p>Here’s the execution flow to help you understand:</p>
<ul>
<li><p><code>Depends(UserAuth)</code> tells FastAPI: “Before running this route, create a <code>UserAuth</code> instance.”</p>
</li>
<li><p>FastAPI extracts name and password from the request URL (for example, <em>/user/dashboard?name=Seke&amp;password=SK99!</em>).</p>
</li>
<li><p>It then calls <code>UserAuth(name=”Seke”, password=”SK99!”)</code> to create the instance.</p>
</li>
</ul>
<ul>
<li><p>The <code>UserAuth</code> instance, with its stored name and password attributes, is passed to the <code>user</code> parameter in <code>get_dashboard</code>.</p>
</li>
<li><p>The route function can access <code>user.name</code> and <code>user.password</code> directly.</p>
</li>
<li><p>If <code>__call__</code> raises an exception, the route never executes.</p>
</li>
</ul>
<p>Test the endpoint with valid credentials from the users list, and you should see output like this: </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762655384549/ac5ab413-0f75-4711-8166-4c99bcca9d7c.jpeg" alt="class dependency output" class="image--center mx-auto" width="557" height="132" loading="lazy"></p>
<p>A closer look at <a target="_blank" href="https://fastapi.tiangolo.com/tutorial/dependencies/classes-as-dependencies/#use-it">FastAPI’s official documentation</a> provides an alternative approach to classes as dependencies. However, using the <code>__call__</code> method, in my opinion, is the most straightforward and self-contained approach. It keeps your authentication logic modular without adding extra code to the path operation.</p>
<p>The trade-off is that class dependencies are more verbose than helper functions, but cleaner for complex logic.</p>
<h2 id="heading-dependency-scope">Dependency Scope</h2>
<p>FastAPI offers two ways to inject dependencies into a path operation: as a <strong>function parameter</strong> or via the <strong>path decorator</strong>. When you include a dependency as a function parameter, the dependency's return value is available within the function. But when injected into the decorator, the dependency executes without passing a return value to the path function.</p>
<p>Beyond single endpoints, FastAPI lets you inject dependencies at the router or global level. Let’s examine these scopes in more detail.</p>
<h3 id="heading-path-operation-level">Path Operation Level</h3>
<p>While the first example injected dependencies into path function parameters, you can also inject them directly into the decorator using the <code>dependencies</code> parameter. This approach is useful for side-effects (for example, authentication guards, rate limiting or request logging) where the return data is not required in the path operation.</p>
<p>Replace the previous code in <code>fastapi-deps/function_deps.py</code> with this:</p>
<pre><code class="lang-python"><span class="hljs-comment">#dep function to pass in decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">user_dep</span>(<span class="hljs-params">name: str, password: str</span>):</span>
    <span class="hljs-keyword">for</span> u <span class="hljs-keyword">in</span> users:
        <span class="hljs-keyword">if</span> u[<span class="hljs-string">"name"</span>] == name <span class="hljs-keyword">and</span> u[<span class="hljs-string">"password"</span>] == password:
            <span class="hljs-keyword">return</span>
    <span class="hljs-keyword">raise</span> HTTPException(status_code=<span class="hljs-number">401</span>, detail=<span class="hljs-string">"Invalid username or password"</span>)

<span class="hljs-comment">#path function</span>
<span class="hljs-meta">@app.get("/users/{user}", dependencies=[Depends(user_dep)])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>() -&gt; dict:</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span> : <span class="hljs-string">"Access granted!"</span>}
</code></pre>
<p>This decorator-based dependency acts as a pre-check before the endpoint executes. It validates credentials without passing any values to the path function. On authentication failure, FastAPI raises an HTTPException and prevents the path operation from running.</p>
<p>If you test this using a valid name and password from the in-memory database, your output should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762656537394/06fc80cf-a8b2-44d2-8955-ec914be699ba.jpeg" alt="path decorator dependency output" class="image--center mx-auto" width="455" height="241" loading="lazy"></p>
<h3 id="heading-router-level">Router Level</h3>
<p>Injecting dependencies at the router level allows multiple endpoints to share common logic without repeating the dependency in each route.</p>
<p>We'll use the same <code>user_dep</code> function but inject it at the router level. Add these imports to <code>fastapi-deps/router_deps.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> APIRouter, Depends

<span class="hljs-comment">#import the dependency function</span>
<span class="hljs-keyword">from</span> function_deps <span class="hljs-keyword">import</span> user_dep
</code></pre>
<p>Then, create an <code>APIRouter</code> instance, passing your dependency to the <code>dependencies</code> parameter. This makes the dependency run automatically for every route you define under this router. </p>
<p>In this example, <code>user_dep</code> executes before <code>get_user()</code> and any other endpoints you add to the router, eliminating the need to declare it on each route.</p>
<pre><code class="lang-python">router = APIRouter(prefix=<span class="hljs-string">"/users"</span>, dependencies=[Depends(user_dep)])

<span class="hljs-comment">#define the routes with or without additional dependencies</span>
<span class="hljs-meta">@router.get("/{user}")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_user</span>() -&gt; dict:</span>
    <span class="hljs-keyword">return</span> {<span class="hljs-string">"message"</span> : <span class="hljs-string">"Access granted!"</span>}
</code></pre>
<p>In your main application file (<code>app.py</code>), import the router and register it with your FastAPI application using <code>include_router()</code>. This makes all routes defined in the router accessible through your application.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI
<span class="hljs-keyword">import</span> uvicorn
<span class="hljs-keyword">from</span> router_deps <span class="hljs-keyword">import</span> router <span class="hljs-keyword">as</span> user_router

app = FastAPI()
app.include_router(user_router)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    uvicorn.run(<span class="hljs-string">"app:app"</span>, reload=<span class="hljs-literal">True</span>)
</code></pre>
<p>Start your server and test the route using a valid name–password pair from the users list, then try a mismatched one. You should get a <strong>200</strong> status for the correct credentials and <strong>401</strong> for invalid ones.</p>
<h3 id="heading-application-level">Application Level</h3>
<p>Application-level dependencies (also called <em>global dependencies</em>) are defined when instantiating the FastAPI app and apply to every route in your application. Unlike router-level dependencies that target specific endpoint groups, app-level dependencies extend across the entire application. Any dependency injected into the FastAPI app object will automatically execute for all path functions.</p>
<p>Let's inject a simple <em>logging</em> dependency alongside the <em>user authentication</em> dependency we've used throughout this article. </p>
<p>Update <code>fastapi-deps/app.py</code> with this code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> fastapi <span class="hljs-keyword">import</span> FastAPI, Depends
<span class="hljs-keyword">import</span> uvicorn
<span class="hljs-keyword">from</span> function_deps <span class="hljs-keyword">import</span> user_dep
<span class="hljs-keyword">from</span> router_deps <span class="hljs-keyword">import</span> router <span class="hljs-keyword">as</span> user_router
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-comment">#Basic logging dependency</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">log_request</span>():</span>
    print(<span class="hljs-string">f"[<span class="hljs-subst">{datetime.now()}</span>] Request received."</span>)

app = FastAPI(dependencies=[Depends(log_request), Depends(user_dep)])
app.include_router(user_router)

<span class="hljs-meta">@app.get("/home")</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_main</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Welcome back!!!"</span>


<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    uvicorn.run(<span class="hljs-string">"app:app"</span>, reload=<span class="hljs-literal">True</span>)
</code></pre>
<p>When you send a request to any endpoint within this application, <code>log_request</code> acknowledges it and outputs what time the request was made. Since we aren’t sending the logs to any database in particular, it will just print to the terminal (or console) like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762673203094/d1c43e1b-0cc2-46e5-ae54-ee4849d1af66.jpeg" alt="logging dependency output in console" class="image--center mx-auto" width="529" height="53" loading="lazy"></p>
<p>Request the endpoint with valid credentials using your browser, cURL, Postman, or the Swagger UI. You should get this response:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762673465276/28d90221-4feb-4467-8c6c-8557dd54de03.jpeg" alt="Server response for API request to home page" class="image--center mx-auto" width="399" height="236" loading="lazy"></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Although the same authentication and logging logic apply to all registered routers, the specific message users see depends on what you program into each router.</div>
</div>

<h2 id="heading-common-use-cases-for-dependency-injection">Common Use Cases for Dependency Injection</h2>
<p>Dependency injection solves several common challenges in API development. Here are the most frequent use cases where you'll apply this pattern.</p>
<ol>
<li><p><strong>Database Connections:</strong> Reusing connection logic across multiple endpoints prevents connection leaks, and ensures each request has an isolated session.</p>
</li>
<li><p><strong>Authentication &amp; Authorization:</strong> Dependencies help validate tokens and verify user roles across protected routes. </p>
</li>
<li><p><strong>Logging &amp; Monitoring:</strong> A logging dependency can automatically record each request to your monitoring system or database. It is beneficial for debugging and tracking API usage.</p>
</li>
<li><p><strong>Rate Limiting:</strong> You can control request frequency and prevent API abuse by injecting rate-limiting logic in path functions.</p>
</li>
<li><p><strong>Configuration &amp; Settings:</strong> FastAPI’s dependency injection system simplifies configuration management by letting you inject settings such as API keys or environment variables wherever needed, keeping your code consistent.</p>
</li>
<li><p><strong>Pagination &amp; Filtering:</strong> Injecting common parameters like page_size and limit standardize data retrieval patterns across endpoints. </p>
</li>
</ol>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>FastAPI's dependency injection system helps you manage shared logic and resources efficiently while adhering to <em>DRY</em> principles. However, knowing when to inject a dependency versus when to skip it is a skill that comes with practice.</p>
<p>Dependency injection isn't needed for simple, standalone logic. But for resources requiring lifecycle management, shared logic, or modularity, FastAPI's dependency injection system simplifies checks and app operations—with or without return values.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Write Unit Tests and E2E Tests for NestJS Applications ]]>
                </title>
                <description>
                    <![CDATA[ Recently, I have been writing unit tests and E2E tests for a NestJS project. This was my first time writing tests for a backend project, and I found the process different from my experience with frontend testing, making it challenging to begin. After... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/nestjs-unit-testing-e2e-testing-guide/</link>
                <guid isPermaLink="false">67ffc1695667d9e59ef9bc46</guid>
                
                    <category>
                        <![CDATA[ nestjs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ E2ETesting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gordan Tan ]]>
                </dc:creator>
                <pubDate>Wed, 16 Apr 2025 14:40:41 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744738441654/1bb2b329-d363-46d7-b091-e0e95ad22c9e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Recently, I have been writing unit tests and E2E tests for a NestJS project. This was my first time writing tests for a backend project, and I found the process different from my experience with frontend testing, making it challenging to begin.</p>
<p>After looking at some examples, I have gained a clearer understanding of how to approach testing. So I wrote an article to record and share my learning to help others who may be facing similar confusion.</p>
<p>In addition, I have put together a demo project with the relevant unit and E2E tests completed, which may be of interest. I’ve <a target="_blank" href="https://github.com/woai3c/nestjs-demo">uploaded the code to Github here</a>.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-difference-between-unit-testing-and-e2e-testing">Difference Between Unit Testing and E2E Testing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-writing-unit-tests">Writing Unit Tests</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-the-first-test-case">The First Test Case</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-second-test-case">The Second Test Case</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-unit-test-coverage">Unit Test Coverage</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-writing-e2e-tests">Writing E2E Tests</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whether-to-write-tests">Whether to Write Tests</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-enhancing-system-robustness">Enhancing System Robustness</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-enhancing-maintainability">Enhancing Maintainability</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-enhancing-development-efficiency">Enhancing Development Efficiency</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-when-not-to-write-tests">When Not to Write Tests?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-reference-materials">Reference Materials</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before diving into this tutorial, you should have:</p>
<ul>
<li><p>Basic knowledge of TypeScript and Node.js</p>
</li>
<li><p>Familiarity with NestJS fundamentals</p>
</li>
<li><p>Understanding of RESTful APIs</p>
</li>
<li><p>MongoDB installed (as the example uses MongoDB)</p>
</li>
<li><p>Node.js and npm/yarn installed on your system</p>
</li>
<li><p>Basic understanding of testing concepts</p>
</li>
</ul>
<p>You can find the complete code examples in the <a target="_blank" href="https://github.com/woai3c/nestjs-demo">demo repository</a>. You can clone it to follow along with the examples.</p>
<h2 id="heading-difference-between-unit-testing-and-e2e-testing">Difference Between Unit Testing and E2E Testing</h2>
<p>Unit tests and E2E tests are methods of software testing, but they have different goals and scopes.</p>
<p>Unit testing involves checking and verifying the smallest testable unit within the software. A function or a method, for example, can be considered a unit. In unit testing, you provide expected outputs for various inputs of a function and validate the correctness of its operation. The goal of unit testing is to quickly identify bugs within the function, and they are easy to write and execute rapidly.</p>
<p>On the other hand, E2E tests often simulate real-world user scenarios to test the entire application. For instance, the frontend typically uses a browser or headless browser for testing, while the backend does so by simulating API calls.</p>
<p>Within a NestJS project, unit tests might assess a specific service or a method of a controller, such as verifying if the <code>update</code> method in the Users module correctly updates a user. An E2E test, however, may examine a complete user journey, from creating a new user to updating their password and eventually deleting the user, which involves multiple services and controllers.</p>
<h2 id="heading-how-to-write-unit-tests">How to Write Unit Tests</h2>
<p>Writing unit tests for a utility function or method that doesn't involve interfaces is relatively straightforward. You only need to consider the various inputs and write the corresponding test code. But the situation becomes more complex once interfaces come into play. Let's use code as an example:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">async</span> validateUser(
  username: <span class="hljs-built_in">string</span>,
  password: <span class="hljs-built_in">string</span>,
): <span class="hljs-built_in">Promise</span>&lt;UserAccountDto&gt; {
  <span class="hljs-keyword">const</span> entity = <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.findOne({ username });
  <span class="hljs-keyword">if</span> (!entity) {
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">'User not found'</span>);
  }
  <span class="hljs-keyword">if</span> (entity.lockUntil &amp;&amp; entity.lockUntil &gt; <span class="hljs-built_in">Date</span>.now()) {
    <span class="hljs-keyword">const</span> diffInSeconds = <span class="hljs-built_in">Math</span>.round((entity.lockUntil - <span class="hljs-built_in">Date</span>.now()) / <span class="hljs-number">1000</span>);
    <span class="hljs-keyword">let</span> message = <span class="hljs-string">`The account is locked. Please try again in <span class="hljs-subst">${diffInSeconds}</span> seconds.`</span>;
    <span class="hljs-keyword">if</span> (diffInSeconds &gt; <span class="hljs-number">60</span>) {
      <span class="hljs-keyword">const</span> diffInMinutes = <span class="hljs-built_in">Math</span>.round(diffInSeconds / <span class="hljs-number">60</span>);
      message = <span class="hljs-string">`The account is locked. Please try again in <span class="hljs-subst">${diffInMinutes}</span> minutes.`</span>;
    }
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(message);
  }
  <span class="hljs-keyword">const</span> passwordMatch = bcrypt.compareSync(password, entity.password);
  <span class="hljs-keyword">if</span> (!passwordMatch) {
    <span class="hljs-comment">// $inc update to increase failedLoginAttempts</span>
    <span class="hljs-keyword">const</span> update = {
      $inc: { failedLoginAttempts: <span class="hljs-number">1</span> },
    };
    <span class="hljs-comment">// lock account when the third try is failed</span>
    <span class="hljs-keyword">if</span> (entity.failedLoginAttempts + <span class="hljs-number">1</span> &gt;= <span class="hljs-number">3</span>) {
      <span class="hljs-comment">// $set update to lock the account for 5 minutes</span>
      update[<span class="hljs-string">'$set'</span>] = { lockUntil: <span class="hljs-built_in">Date</span>.now() + <span class="hljs-number">5</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span> };
    }
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.update(entity._id, update);
    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">'Invalid password'</span>);
  }
  <span class="hljs-comment">// if validation is sucessful, then reset failedLoginAttempts and lockUntil</span>
  <span class="hljs-keyword">if</span> (
    entity.failedLoginAttempts &gt; <span class="hljs-number">0</span> ||
    (entity.lockUntil &amp;&amp; entity.lockUntil &gt; <span class="hljs-built_in">Date</span>.now())
  ) {
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.usersService.update(entity._id, {
      $set: { failedLoginAttempts: <span class="hljs-number">0</span>, lockUntil: <span class="hljs-literal">null</span> },
    });
  }
  <span class="hljs-keyword">return</span> { userId: entity._id, username } <span class="hljs-keyword">as</span> UserAccountDto;
}
</code></pre>
<p>The code above is a method <code>validateUser</code> in the <code>auth.service.ts</code> file, primarily used to verify whether the username and password entered by the user during login are correct. It contains the following logic:</p>
<ol>
<li><p>Check if the user exists based on <code>username</code>. If not, throw a 401 exception (a 404 exception is also feasible).</p>
</li>
<li><p>See if the user is locked out. If so, throw a 401 exception with a relevant message.</p>
</li>
<li><p>Encrypt the <code>password</code> and compare it with the password in the database. If it's incorrect, throw a 401 exception (three consecutive failed login attempts will lock the account for 5 minutes).</p>
</li>
<li><p>If the login is successful, clear any previously failed login attempt counts (if applicable) and return the user <code>id</code> and <code>username</code> to the next stage.</p>
</li>
</ol>
<p>As you can see, the <code>validateUser</code> method includes four processing logics. So we need to write corresponding unit test code for these four points to ensure that the entire <code>validateUser</code> function is operating correctly.</p>
<h3 id="heading-the-first-test-case">The First Test Case</h3>
<p>When we start writing unit tests, we encounter a problem: the <code>findOne</code> method needs to interact with the database, and it looks for corresponding users in the database through <code>username</code>. But if every unit test has to interact with the database, the testing will become very cumbersome. So we can mock fake data to achieve this.</p>
<p>For example, assume we have registered a user named <code>woai3c</code>. Then, during login, the user data can be retrieved in the <code>validateUser</code> method through <code>const entity = await this.usersService.findOne({ username });</code>. As long as this line of code can return the desired data, there is no problem, even without database interaction. We can achieve this through mock data.</p>
<p>Now, let's look at the relevant test code for the <code>validateUser</code> method:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">import</span> { Test } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/testing'</span>;
<span class="hljs-keyword">import</span> { AuthService } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/modules/auth/auth.service'</span>;
<span class="hljs-keyword">import</span> { UsersService } <span class="hljs-keyword">from</span> <span class="hljs-string">'@/modules/users/users.service'</span>;
<span class="hljs-keyword">import</span> { UnauthorizedException } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;
<span class="hljs-keyword">import</span> { TEST_USER_NAME, TEST_USER_PASSWORD } <span class="hljs-keyword">from</span> <span class="hljs-string">'@tests/constants'</span>;
describe(<span class="hljs-string">'AuthService'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">let</span> authService: AuthService; <span class="hljs-comment">// Use the actual AuthService type</span>
  <span class="hljs-keyword">let</span> usersService: Partial&lt;Record&lt;keyof UsersService, jest.Mock&gt;&gt;;
  beforeEach(<span class="hljs-keyword">async</span> () =&gt; {
    usersService = {
      findOne: jest.fn(),
    };
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">module</span> = await Test.createTestingModule({
      providers: [        AuthService,
        {
          provide: UsersService,
          useValue: usersService,
        },
      ],
    }).compile();
    authService = <span class="hljs-built_in">module</span>.get&lt;AuthService&gt;(AuthService);
  });
  describe(<span class="hljs-string">'validateUser'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'should throw an UnauthorizedException if user is not found'</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">await</span> expect(
        authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD),
      ).rejects.toThrow(UnauthorizedException);
    });
    <span class="hljs-comment">// other tests...</span>
  });
});
</code></pre>
<p>We get the user data by calling the <code>findOne</code> method of <code>usersService</code>, so we need to mock the <code>findOne</code> method of <code>usersService</code> in the test code:</p>
<pre><code class="lang-typescript">beforeEach(<span class="hljs-keyword">async</span> () =&gt; {
    usersService = {
      findOne: jest.fn(), <span class="hljs-comment">// mock findOne method</span>
    };
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">module</span> = await Test.createTestingModule({
      providers: [        AuthService, <span class="hljs-comment">// real AuthService, because we are testing its methods</span>
        {
          provide: UsersService, <span class="hljs-comment">// use mock usersService instead of real usersService</span>
          useValue: usersService,
        },
      ],
    }).compile();
    authService = <span class="hljs-built_in">module</span>.get&lt;AuthService&gt;(AuthService);
  });
</code></pre>
<p>We use <code>jest.fn()</code> to return a function to replace the real <code>usersService.findOne()</code>. If <code>usersService.findOne()</code> is called now, there will be no return value, so the first unit test case will pass:</p>
<pre><code class="lang-typescript">it(<span class="hljs-string">'should throw an UnauthorizedException if user is not found'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> expect(
    authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD),
  ).rejects.toThrow(UnauthorizedException);
});
</code></pre>
<p>Since <code>findOne</code> in <code>const entity = await this.usersService.findOne({ username });</code> of the <code>validateUser</code> method is a mocked fake function with no return value, the 2nd to 4th lines of code in the <code>validateUser</code> method could execute:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">if</span> (!entity) {
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(<span class="hljs-string">'User not found'</span>);
}
</code></pre>
<p>It throws a 401 error, which is as expected.</p>
<h3 id="heading-the-second-test-case">The Second Test Case</h3>
<p>The second logic in the <code>validateUser</code> method is to determine if the user is locked, with the corresponding code as follows:</p>
<pre><code class="lang-typescript"><span class="hljs-keyword">if</span> (entity.lockUntil &amp;&amp; entity.lockUntil &gt; <span class="hljs-built_in">Date</span>.now()) {
  <span class="hljs-keyword">const</span> diffInSeconds = <span class="hljs-built_in">Math</span>.round((entity.lockUntil - <span class="hljs-built_in">Date</span>.now()) / <span class="hljs-number">1000</span>);
  <span class="hljs-keyword">let</span> message = <span class="hljs-string">`The account is locked. Please try again in <span class="hljs-subst">${diffInSeconds}</span> seconds.`</span>;
  <span class="hljs-keyword">if</span> (diffInSeconds &gt; <span class="hljs-number">60</span>) {
    <span class="hljs-keyword">const</span> diffInMinutes = <span class="hljs-built_in">Math</span>.round(diffInSeconds / <span class="hljs-number">60</span>);
    message = <span class="hljs-string">`The account is locked. Please try again in <span class="hljs-subst">${diffInMinutes}</span> minutes.`</span>;
  }
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> UnauthorizedException(message);
}
</code></pre>
<p>As you can see, we can determine that the current account is locked if there is a lock time <code>lockUntil</code> in the user data and the lock end time is greater than the current time. So we need to mock a user data with the <code>lockUntil</code> field:</p>
<pre><code class="lang-typescript">it(<span class="hljs-string">'should throw an UnauthorizedException if the account is locked'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> lockedUser = {
    _id: TEST_USER_ID,
    username: TEST_USER_NAME,
    password: TEST_USER_PASSWORD,
    lockUntil: <span class="hljs-built_in">Date</span>.now() + <span class="hljs-number">1000</span> * <span class="hljs-number">60</span> * <span class="hljs-number">5</span>, <span class="hljs-comment">// The account is locked for 5 minutes</span>
  };
  usersService.findOne.mockResolvedValueOnce(lockedUser);
  <span class="hljs-keyword">await</span> expect(
    authService.validateUser(TEST_USER_NAME, TEST_USER_PASSWORD),
  ).rejects.toThrow(UnauthorizedException);
});
</code></pre>
<p>In the test code above, an object <code>lockedUser</code> is first defined, which contains the <code>lockUntil</code> field we need. Then, it is used as the return value for <code>findOne</code>, achieved by <code>usersService.findOne.mockResolvedValueOnce(lockedUser);</code>. Thus, when the <code>validateUser</code> method is executed, the user data within it is the mocked data, successfully allowing the second test case to pass.</p>
<h3 id="heading-unit-test-coverage">Unit Test Coverage</h3>
<p>Unit test coverage (Code Coverage) is a metric used to describe how much of the application code has been covered or tested by unit tests. It is typically expressed as a percentage, indicating how much of all possible code paths have been covered by test cases.</p>
<p>Unit test coverage usually includes the following types:</p>
<ul>
<li><p>Line Coverage: How many lines of code are covered by the tests.</p>
</li>
<li><p>Function Coverage: How many functions or methods are covered by the tests.</p>
</li>
<li><p>Branch Coverage: How many code branches are covered by the tests (for example, <code>if/else</code> statements).</p>
</li>
<li><p>Statement Coverage: How many statements in the code are covered by the tests.</p>
</li>
</ul>
<p>Unit test coverage is an important metric to measure the quality of unit tests, but it is not the only metric. A high coverage rate can help to detect errors in the code, but it does not guarantee the quality of the code. A low coverage rate may mean that there is untested code, potentially with undetected errors.</p>
<p>The image below shows the unit test coverage results for a demo project:</p>
<p><a target="_blank" href="https://camo.githubusercontent.com/e3de4ecc6be093ac92a514fa183f688c455b00cc15a3d003bfe2f25e31a08c4f/68747470733a2f2f6d69726f2e6d656469756d2e636f6d2f76322f726573697a653a6669743a313331302f666f726d61743a776562702f302a515a5f4d4a77774c715752314d3136652e706e67"><img src="https://camo.githubusercontent.com/e3de4ecc6be093ac92a514fa183f688c455b00cc15a3d003bfe2f25e31a08c4f/68747470733a2f2f6d69726f2e6d656469756d2e636f6d2f76322f726573697a653a6669743a313331302f666f726d61743a776562702f302a515a5f4d4a77774c715752314d3136652e706e67" alt="Unit test coverage overview showing test results with percentages for statements, branches, functions, and lines" width="600" height="400" loading="lazy"></a></p>
<p>For files like services and controllers, it's generally better to have a higher unit test coverage, while for files like modules there's no need to write unit tests – nor is it possible to write them, as it's meaningless.</p>
<p>This is because NestJS modules are primarily configuration files that define the structure of your application by connecting controllers, services, and other components together. They don't contain actual business logic to test, but rather serve as wiring instructions for the dependency injection system. Testing modules would only verify that NestJS's core functionality works correctly, which is already tested by the NestJS team themselves.</p>
<p>The above image represents the overall metrics for the entire unit test coverage. If you want to view the test coverage for a specific function, you can open the <code>coverage/lcov-report/index.html</code> file in the project's root directory. For example, I want to see the specific test situation for the <code>validateUser</code> method:</p>
<p><a target="_blank" href="https://camo.githubusercontent.com/e5757001ae5bfec61c2b3ed19f7ef99cffc6c014480d7dad17ab28a2713f6aa0/68747470733a2f2f6d69726f2e6d656469756d2e636f6d2f76322f726573697a653a6669743a313430302f666f726d61743a776562702f302a4e32542d44694d754566776b332d33322e706e67"><img src="https://camo.githubusercontent.com/e5757001ae5bfec61c2b3ed19f7ef99cffc6c014480d7dad17ab28a2713f6aa0/68747470733a2f2f6d69726f2e6d656469756d2e636f6d2f76322f726573697a653a6669743a313430302f666f726d61743a776562702f302a4e32542d44694d754566776b332d33322e706e67" alt="Detailed test coverage for the validateUser method showing specific uncovered lines highlighted in red" width="600" height="400" loading="lazy"></a></p>
<p>As you can see, the original unit test coverage for the <code>validateUser</code> method is not 100%, and there are still two lines of code that were not executed. But it doesn't matter much, as it does not affect the four key processing nodes, and we shouldn’t pursue high test coverage unidimensionally.</p>
<h2 id="heading-how-to-write-e2e-tests">How to Write E2E Tests</h2>
<p>In the unit tests section, you learned how to write unit tests for each feature of the <code>validateUser()</code> function, using mocked data to ensure that each feature could be tested.</p>
<p>In e2E testing, we need to simulate real user scenarios, so connecting to a database for testing is necessary. So, the methods in the <code>auth.service.ts</code> module that we'll be testing all interact with the database.</p>
<p>The <code>auth</code> module primarily includes the following features:</p>
<ul>
<li><p>Registration</p>
</li>
<li><p>Login</p>
</li>
<li><p>Token refresh</p>
</li>
<li><p>Reading user information</p>
</li>
<li><p>Changing password</p>
</li>
<li><p>Deleting users</p>
</li>
</ul>
<p>E2E tests need to test these six features one by one, starting with <code>registration</code> and ending with <code>deleting users</code>. During testing, we can create a dedicated test user to conduct the tests and then delete this test user upon completion, so we don’t leave any unnecessary information in the test database.</p>
<pre><code class="lang-typescript">beforeAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> moduleFixture: TestingModule = <span class="hljs-keyword">await</span> Test.createTestingModule({
    imports: [AppModule],
  }).compile()
  app = moduleFixture.createNestApplication()
  <span class="hljs-keyword">await</span> app.init()
  <span class="hljs-comment">// Perform a login to obtain a token</span>
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> request(app.getHttpServer())
    .post(<span class="hljs-string">'/auth/register'</span>)
    .send({ username: TEST_USER_NAME, password: TEST_USER_PASSWORD })
    .expect(<span class="hljs-number">201</span>)
  accessToken = response.body.access_token
  refreshToken = response.body.refresh_token
})
afterAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> request(app.getHttpServer())
    .delete(<span class="hljs-string">'/auth/delete-user'</span>)
    .set(<span class="hljs-string">'Authorization'</span>, <span class="hljs-string">`Bearer <span class="hljs-subst">${accessToken}</span>`</span>)
    .expect(<span class="hljs-number">200</span>)
  <span class="hljs-keyword">await</span> app.close()
})
</code></pre>
<p>The <code>beforeAll</code> hook function runs before all tests begin, so we can register a test account <code>TEST_USER_NAME</code> here. The <code>afterAll</code> hook function runs after all tests end, so it's suitable to delete the test account <code>TEST_USER_NAME</code> here. It also conveniently tests the registration and deletion functions.</p>
<p>In the previous section's unit tests, we wrote relevant unit tests around the <code>validateUser</code> method. Actually, this method is executed during login to validate if the user's account and password are correct. So this E2E test will also use the login process to demonstrate how to compose the E2E test cases.</p>
<p>The entire login test process includes five small tests:</p>
<pre><code class="lang-typescript">describe(<span class="hljs-string">'login'</span>, <span class="hljs-function">() =&gt;</span> {
    it(<span class="hljs-string">'/auth/login (POST)'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// ...</span>
    })
    it(<span class="hljs-string">'/auth/login (POST) with user not found'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// ...</span>
    })
    it(<span class="hljs-string">'/auth/login (POST) without username or password'</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-comment">// ...</span>
    })
    it(<span class="hljs-string">'/auth/login (POST) with invalid password'</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// ...</span>
    })
    it(<span class="hljs-string">'/auth/login (POST) account lock after multiple failed attempts'</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-comment">// ...</span>
    })
  })
</code></pre>
<p>These five tests are as follows:</p>
<ol>
<li><p>Successful login, return 200</p>
</li>
<li><p>If the user does not exist, throw a 401 exception</p>
</li>
<li><p>If password or username is not provided, throw a 400 exception</p>
</li>
<li><p>Login with the wrong password, throw a 401 exception</p>
</li>
<li><p>If the account is locked, throw a 401 exception</p>
</li>
</ol>
<p>Now let's start writing the E2E tests:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// login success</span>
it(<span class="hljs-string">'/auth/login (POST)'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> request(app.getHttpServer())
    .post(<span class="hljs-string">'/auth/login'</span>)
    .send({ username: TEST_USER_NAME, password: TEST_USER_PASSWORD })
    .expect(<span class="hljs-number">200</span>)
})
<span class="hljs-comment">// if user not found, should throw 401 exception</span>
it(<span class="hljs-string">'/auth/login (POST) with user not found'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> request(app.getHttpServer())
    .post(<span class="hljs-string">'/auth/login'</span>)
    .send({ username: TEST_USER_NAME2, password: TEST_USER_PASSWORD })
    .expect(<span class="hljs-number">401</span>) <span class="hljs-comment">// Expect an unauthorized error</span>
})
</code></pre>
<p>Writing E2E test code is relatively straightforward: you simply call the interface and then verify the result. For example, for the successful login test, we just need to verify that the returned result is 200.</p>
<p>The first four tests are quite simple. Now let's look at a slightly more complicated E2E test, which is to verify whether an account is locked.</p>
<pre><code class="lang-typescript">it(<span class="hljs-string">'/auth/login (POST) account lock after multiple failed attempts'</span>, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> moduleFixture: TestingModule = <span class="hljs-keyword">await</span> Test.createTestingModule({
    imports: [AppModule],
  }).compile()
  <span class="hljs-keyword">const</span> app = moduleFixture.createNestApplication()
  <span class="hljs-keyword">await</span> app.init()
  <span class="hljs-keyword">const</span> registerResponse = <span class="hljs-keyword">await</span> request(app.getHttpServer())
    .post(<span class="hljs-string">'/auth/register'</span>)
    .send({ username: TEST_USER_NAME2, password: TEST_USER_PASSWORD })
  <span class="hljs-keyword">const</span> accessToken = registerResponse.body.access_token
  <span class="hljs-keyword">const</span> maxLoginAttempts = <span class="hljs-number">3</span> <span class="hljs-comment">// lock user when the third try is failed</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; maxLoginAttempts; i++) {
    <span class="hljs-keyword">await</span> request(app.getHttpServer())
      .post(<span class="hljs-string">'/auth/login'</span>)
      .send({ username: TEST_USER_NAME2, password: <span class="hljs-string">'InvalidPassword'</span> })
  }
  <span class="hljs-comment">// The account is locked after the third failed login attempt</span>
  <span class="hljs-keyword">await</span> request(app.getHttpServer())
    .post(<span class="hljs-string">'/auth/login'</span>)
    .send({ username: TEST_USER_NAME2, password: TEST_USER_PASSWORD })
    .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> {
      expect(res.body.message).toContain(
        <span class="hljs-string">'The account is locked. Please try again in 5 minutes.'</span>,
      )
    })
  <span class="hljs-keyword">await</span> request(app.getHttpServer())
    .delete(<span class="hljs-string">'/auth/delete-user'</span>)
    .set(<span class="hljs-string">'Authorization'</span>, <span class="hljs-string">`Bearer <span class="hljs-subst">${accessToken}</span>`</span>)
  <span class="hljs-keyword">await</span> app.close()
})
</code></pre>
<p>When a user fails to log in three times in a row, the account will be locked. So in this test, we cannot use the test account <code>TEST_USER_NAME</code>, because if the test is successful, this account will be locked and unable to continue the following tests. We need to register another new user <code>TEST_USER_NAME2</code> specifically to test account locking, and delete this user after the test is successful.</p>
<p>So, as you can see, the code for this E2E test is quite substantial, requiring a lot of setup and teardown work, but the actual test code is just these few lines:</p>
<pre><code class="lang-typescript"><span class="hljs-comment">// login three times</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; maxLoginAttempts; i++) {
  <span class="hljs-keyword">await</span> request(app.getHttpServer())
    .post(<span class="hljs-string">'/auth/login'</span>)
    .send({ username: TEST_USER_NAME2, password: <span class="hljs-string">'InvalidPassword'</span> })
}
<span class="hljs-comment">// test if the account is locked</span>
<span class="hljs-keyword">await</span> request(app.getHttpServer())
  .post(<span class="hljs-string">'/auth/login'</span>)
  .send({ username: TEST_USER_NAME2, password: TEST_USER_PASSWORD })
  .then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> {
    expect(res.body.message).toContain(
      <span class="hljs-string">'The account is locked. Please try again in 5 minutes.'</span>,
    )
  })
</code></pre>
<p>Writing E2E test code is relatively simple. You don't need to consider mock data or test coverage. It's sufficient if the entire system process runs as expected.</p>
<h2 id="heading-when-to-write-tests">When to Write Tests</h2>
<p>If possible, I generally recommend writing tests. Doing so can enhance the robustness, maintainability, and development efficiency of the system. Here are some key reasons why writing tests is useful:</p>
<h3 id="heading-enhancing-system-robustness">Enhancing System Robustness</h3>
<p>When writing code, you usually focus on the program flow under normal inputs to ensure the core functionality works properly. But you might often overlook some edge cases, such as abnormal inputs.</p>
<p>Writing tests changes this, as it forces you to consider how to handle these cases and respond appropriately, thus preventing crashes. So we can say that writing tests indirectly improves system robustness.</p>
<h3 id="heading-enhancing-maintainability">Enhancing Maintainability</h3>
<p>Taking over a new project that includes comprehensive tests can be very pleasant. They act as a guide, helping you quickly understand the various functionalities. Just by looking at the test code, you can easily grasp the expected behavior and boundary conditions of each function without having to go through each line of the function's code.</p>
<h3 id="heading-enhancing-development-efficiency">Enhancing Development Efficiency</h3>
<p>Imagine a project that hasn't been updated for a while suddenly receives new requirements. After making changes, you might worry about introducing bugs. Without tests, you would need to manually test the entire project again — wasting time and being inefficient.</p>
<p>With complete tests, a single command can tell you whether the code changes have impacted existing functionalities. Even if there are errors, you can quickly locate them and address them.</p>
<h2 id="heading-when-not-to-write-tests">When Not to Write Tests</h2>
<p>For short-term projects and projects with very fast requirement iterations, it's not recommended to write tests.</p>
<p>For example, a project built for an event that will be useless after the event ends doesn't need tests. Also, for projects that undergo very fast requirement iterations, writing tests could enhance development efficiency, but that's based on the premise that function iterations are slow. If the function you just completed changes in a day or two, the related test code must be rewritten.</p>
<p>So, it's better not to write tests at all in these cases and rely on the testing team instead – because writing tests is very time-consuming and not worth the effort for these situations.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I’ve explained in detail how to write unit tests and E2E tests for NestJS projects. But I still want to reiterate the importance of testing. It can enhance the robustness, maintainability, and development efficiency of the system.</p>
<p>If you don't have the opportunity to write tests, I suggest you start a practice project yourself or participate in some open-source projects and contribute code to them. Open-source projects generally have stricter code requirements. Contributing code may require you to write new test cases or modify existing ones.</p>
<h3 id="heading-reference-materials">Reference Materials</h3>
<ul>
<li><p><a target="_blank" href="https://nestjs.com/">NestJS</a>: A framework for building efficient, scalable Node.js server-side applications.</p>
</li>
<li><p><a target="_blank" href="https://www.mongodb.com/">MongoDB</a>: A NoSQL database used for data storage.</p>
</li>
<li><p><a target="_blank" href="https://jestjs.io/">Jest</a>: A testing framework for JavaScript and TypeScript.</p>
</li>
<li><p><a target="_blank" href="https://github.com/visionmedia/supertest">Supertest</a>: A library for testing HTTP servers.</p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is Backend as a Service (BaaS)? A Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ Building an authentication system can be complex, often requiring a server to store user data. Sometimes, you need a faster, easier solution. For those new to development or without technical expertise, managing servers, databases, and user logins ca... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/backend-as-a-service-beginners-guide/</link>
                <guid isPermaLink="false">67b30da662ec9a593dfeb4a7</guid>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Databases ]]>
                    </category>
                
                    <category>
                        <![CDATA[ authentication ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ijeoma Igboagu ]]>
                </dc:creator>
                <pubDate>Mon, 17 Feb 2025 10:21:26 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739291731037/169ad924-9bcb-4af2-9281-fad2488a868d.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building an authentication system can be complex, often requiring a server to store user data. Sometimes, you need a faster, easier solution.</p>
<p>For those new to development or without technical expertise, managing servers, databases, and user logins can be overwhelming. This is where Backend as a Service (BaaS) helps.</p>
<p>BaaS platforms provide ready-made backend solutions, making app development simpler. Whether you're a developer or someone with no coding experience, BaaS allows you to focus on your app’s features instead of handling backend complexities.</p>
<p>​​This article will explore BaaS, its features, pricing, and popular BaaS​ tools.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-backend-as-a-service-baas">​​​What is Backend as a Service (BaaS)?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-features-of-baas">Key Features of Baas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-use-backend-as-a-service-baas">Why use Backend as a Service (BaaS)?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-backend-as-a-service-baas">When to Use Backend as a Service (BaaS)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-the-popular-backend-as-a-service-baas-tools">What are the Popular Backend as a Service (BaaS) Tools?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-get-started-with-baas-quick-example">How to Get Started with BaaS (Quick Example)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-backend-as-a-service-baas">​​​What is Backend as a Service (BaaS)?</h2>
<p>BaaS is a cloud platform that provides pre-built backend infrastructure and services. It eliminates the need for developers to manage servers, databases, and other backend tasks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739537937739/4ae3bb03-1196-4298-9299-a0a09c4bd41d.png" alt="Graphical interface of BaaS" width="600" height="400" loading="lazy"></p>
<p>​​<strong>Source:</strong> <a target="_blank" href="https://www.cloudflare.com/fr-fr/learning/serverless/glossary/backend-as-a-service-baas/">https://www.cloudflare.com</a></p>
<h2 id="heading-key-features-of-baas">​​Key Features of BaaS</h2>
<p>Here are some features of BaaS:</p>
<ul>
<li><p>BaaS makes it easy to create and manage user accounts and logins without much coding.</p>
</li>
<li><p>It lets you store and manage data, eliminating the need to set up a database from scratch.</p>
</li>
<li><p>BaaS comes with tools (APIs and SDKs) that help connect your application to the backend easily.</p>
</li>
<li><p>Many BaaS platforms let you see updates in real time, so your application can show live data to users.</p>
</li>
<li><p>BaaS offers space in the cloud to store files and images, making it easy to handle user uploads.</p>
</li>
<li><p>You don’t need to worry about managing servers—BaaS takes care of that for you, so you can focus on building your application.</p>
</li>
<li><p>Some BaaS platforms allow you to send notifications to users about updates or messages.</p>
</li>
<li><p>BaaS often provides tools to track user interactions, helping you understand what works and what doesn’t.</p>
</li>
<li><p>It also makes it easy to integrate with other services like payment systems and social media with minimal effort.</p>
</li>
<li><p>As your app grows, BaaS scales with it, handling more users and data seamlessly.</p>
</li>
</ul>
<h2 id="heading-why-use-backend-as-a-service-baas">Why use Backend as a Service (BaaS)?</h2>
<p>There are several key reasons why BaaS is an excellent choice for developers:</p>
<ul>
<li><p>Pre-built features reduce development time, allowing you to focus on design and functionality instead of backend issues.</p>
</li>
<li><p>With BaaS, you don’t have to worry about servers, scaling, or security updates—the provider takes care of it all.</p>
</li>
<li><p>Most BaaS platforms offer essential features like user authentication, data storage, and real-time updates, helping you build your app without starting from scratch.</p>
</li>
<li><p>As your application gets more users, BaaS can handle it! These services adjust to support more users and data, so you can focus on growing your app.</p>
</li>
<li><p>BaaS handles the infrastructure so you don’t need to spend time or money on the backend. This allows you to focus on design and creating user experiences that add value to your users.</p>
</li>
</ul>
<h2 id="heading-when-to-use-backend-as-a-service-baas">When to Use Backend as a Service (BaaS)</h2>
<p>BaaS is perfect for building an app in a short amount of time without managing the backend. Here are the scenarios when BaaS makes sense:</p>
<ul>
<li><p>BaaS handles your app’s backend, letting you focus on its features. <strong>For example,</strong> when building a to-do list app, BaaS makes it easy to manage user logins and task data without setting up servers from scratch.</p>
</li>
<li><p>For small teams or solo devs, BaaS handles the backend. You do not need extra resources.</p>
</li>
<li><p>If you're launching a startup, Baas lets you release a Minimum Viable Product (MVP) without delay. It helps you speed up development and cut costs. </p>
</li>
<li><p>If your app needs features like user authentication, data storage, or push notifications, BaaS provides them out of the box. For example, when building a social media app, BaaS simplifies user logins and file uploads, saving you from starting from scratch.</p>
</li>
<li><p>BaaS automatically scales to support more users, allowing you to focus on improving your app. For example, a small multiplayer game can start with a few players, and as it grows, BaaS will seamlessly handle thousands without extra backend effort.</p>
</li>
</ul>
<h2 id="heading-what-are-the-popular-backend-as-a-service-baas-tools">What are the Popular Backend as a Service (BaaS) Tools?</h2>
<p>If you're looking to explore BaaS, here are popular platforms you can use:</p>
<h3 id="heading-clerk"><strong>Clerk</strong></h3>
<p>Clerk software focuses on user management. It offers tools for authentication, user profiles, and permissions management. It’s great for developers who need simple user management in their apps.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730034843051_FireShot+Capture+598+-+Clerk+-+Authentication+and+User+Management+-+clerk.com.png" alt="The Graphical Interface of Clerk" width="600" height="400" loading="lazy"></p>
<h3 id="heading-features-of-clerk"><strong>Features of clerk</strong></h3>
<p>Clerk provides:</p>
<ul>
<li><p>Multi-factor authentication (MFA)</p>
</li>
<li><p>Passwordless login (magic links, OTPs)</p>
</li>
<li><p>Social &amp; OAuth login (Google, GitHub, and so on)</p>
</li>
<li><p>Enterprise SSO (SAML, OAuth)</p>
</li>
<li><p>Biometric login (Face ID, Touch ID)</p>
</li>
</ul>
<p>It also handles:</p>
<ul>
<li><p>User profiles &amp; custom attributes</p>
</li>
<li><p>Roles &amp; permissions</p>
</li>
<li><p>Teams &amp; organizations</p>
</li>
<li><p>Session management</p>
</li>
</ul>
<p>For security, it offers:</p>
<ul>
<li><p>Token-based authentication (JWT)</p>
</li>
<li><p>Rate limiting</p>
</li>
<li><p>Audit logs</p>
</li>
<li><p>GDPR &amp; SOC 2 compliance</p>
</li>
</ul>
<p>For developers, it comes with:</p>
<ul>
<li><p>Prebuilt UI components</p>
</li>
<li><p>SDKs for React, Next.js, Vue, and so on</p>
</li>
<li><p>Custom email &amp; SMS templates</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://clerk.com/">Clerk</a></p>
<h3 id="heading-pricing"><strong>Pricing</strong></h3>
<p>Clerk offers a <strong>Free Plan</strong> that includes up to 10,000 Monthly Active Users (MAUs) at no cost. For more advanced features, the <strong>Pro Plan</strong> is available at $25 per month, which also includes the first 10,000 MAUs.</p>
<p>For detailed and up-to-date information on Clerk's pricing plans, please visit their <a target="_blank" href="https://clerk.com/pricing">official pricing page</a>:</p>
<h3 id="heading-firebase"><strong>Firebase</strong></h3>
<p>Firebase is a Google-backed BaaS platform. It is known for its real-time databases, authentication, and cloud storage. It also has easy-to-use tools for web and mobile apps.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730035263750_FireShot+Capture+599+-+Firebase+-+Googles+Mobile+and+Web+App+Development+Platform_+-+firebase.google.com.png" alt="The Graphical Interface of Firebase" width="600" height="400" loading="lazy"></p>
<h3 id="heading-features-of-firebase">Features of Firebase</h3>
<p>Firebase provides:</p>
<h3 id="heading-backend-services"><strong>Backend Services</strong></h3>
<ul>
<li><p>Firestore &amp; Realtime Database</p>
</li>
<li><p>Cloud Storage</p>
</li>
<li><p>Serverless Functions</p>
</li>
<li><p>Web Hosting</p>
</li>
</ul>
<h3 id="heading-authentication"><strong>Authentication</strong></h3>
<ul>
<li><p>Email &amp; password login</p>
</li>
<li><p>Social logins (Google, Facebook, and so on)</p>
</li>
<li><p>Phone authentication</p>
</li>
<li><p>Anonymous sign-in</p>
</li>
</ul>
<h3 id="heading-analytics-amp-monitoring"><strong>Analytics &amp; Monitoring</strong></h3>
<ul>
<li><p>Google Analytics</p>
</li>
<li><p>Crash tracking (Crashlytics)</p>
</li>
<li><p>Performance monitoring</p>
</li>
<li><p>A/B testing</p>
</li>
</ul>
<h3 id="heading-engagement-tools"><strong>Engagement Tools</strong></h3>
<ul>
<li><p>Push notifications</p>
</li>
<li><p>Remote app updates</p>
</li>
<li><p>In-app messaging</p>
</li>
</ul>
<h3 id="heading-machine-learning"><strong>Machine Learning</strong></h3>
<ul>
<li><p>Text recognition</p>
</li>
<li><p>Image labelling</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://firebase.google.com/">Firebase</a></p>
<h3 id="heading-pricing-plan">Pricing plan</h3>
<p>Firebase offers a <strong>Spark Plan</strong> (free tier) and a <strong>Blaze Plan</strong> (pay-as-you-go). The Spark Plan provides limited free usage, while the Blaze Plan charges based on your actual usage. For detailed and up-to-date information on Firebase's pricing plans, please visit their <a target="_blank" href="https://firebase.google.com/pricing">official pricing page</a>.</p>
<h3 id="heading-convex"><strong>Convex</strong></h3>
<p>Convex is a serverless BaaS platform. It provides real-time data sync and scalable backend services. The design simplifies serverless computing for developers.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730035688864_FireShot+Capture+600+-+Convex+-+The+fullstack+TypeScript+development+platform+-+www.convex.dev.png" alt="The Graphical Interface of Convex" width="600" height="400" loading="lazy"></p>
<h3 id="heading-convex-features"><strong>Convex Features</strong></h3>
<ul>
<li><p><strong>Database</strong> – Real-time data storage</p>
</li>
<li><p><strong>Serverless Functions</strong> – Run backend logic without managing servers</p>
</li>
<li><p><strong>Authentication</strong> – Built-in user auth &amp; access control</p>
</li>
<li><p><strong>Caching</strong> – Faster data retrieval</p>
</li>
<li><p><strong>Webhooks &amp; Crons</strong> – Automate tasks &amp; trigger events</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://www.convex.dev/">Convex</a></p>
<h3 id="heading-pricing-1"><strong>Pricing</strong></h3>
<ul>
<li><p><strong>Free Plan</strong> – Limited resources for small projects</p>
</li>
<li><p><strong>Pro Plan</strong> – Pay-as-you-go based on usage</p>
</li>
</ul>
<p>Check out full details for <a target="_blank" href="https://convex.dev/pricing">convex pricing</a></p>
<h3 id="heading-8base"><strong>8base</strong></h3>
<p>A low-code platform that allows developers to build serverless apps with minimal setup. It provides database management, authentication, and API development tools.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730036229410_gui+8base.png" alt="The Graphical Interface of 8base" width="600" height="400" loading="lazy"></p>
<h3 id="heading-8base-features"><strong>8base Features</strong></h3>
<ul>
<li><p><strong>Backend Builder</strong> – Manage your database easily.</p>
</li>
<li><p><strong>Serverless Functions</strong> – Run custom backend logic.</p>
</li>
<li><p><strong>GraphQL API</strong> – Auto-generated API for your data.</p>
</li>
<li><p><strong>Authentication</strong> – Built-in user login &amp; access control.</p>
</li>
<li><p><strong>File Management</strong> – Store and manage files.</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://www.8base.com/">8base</a></p>
<h3 id="heading-pricing-2"><strong>Pricing</strong></h3>
<ul>
<li><p><strong>Free Plan</strong> – $0/month (1 developer, basic features).</p>
</li>
<li><p><strong>Developer Plan</strong> – $25/month per developer.</p>
</li>
<li><p><strong>Professional Plan</strong> – $150/month (5 developers).</p>
</li>
<li><p><strong>Custom Plan</strong> – Contact 8base for enterprise solutions.</p>
</li>
</ul>
<p>Check out full pricing details here: <a target="_blank" href="https://www.8base.com/pricing">8base Pricing</a></p>
<h3 id="heading-backendless"><strong>Backendless</strong></h3>
<p>Backendless is a no-code platform that makes app development easy. It provides APIs, data storage, user management, and real-time updates in one place.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730036359851_FireShot+Capture+584+-+Backendless+Visual+App+Development+Platform+-+UI+Backend++Database_+-+backendless.com.png" alt="The Graphical Interface of Backendless" width="600" height="400" loading="lazy"></p>
<h3 id="heading-features">Features</h3>
<ul>
<li><p><strong>UI Builder</strong>: Design your app's front end visually without coding.</p>
</li>
<li><p><strong>Real-Time Database</strong>: Store and sync data in real-time across clients.</p>
</li>
<li><p><strong>User Authentication</strong>: Manage user sign-ups, logins, and roles.</p>
</li>
<li><p><strong>Cloud Code</strong>: Implement custom server-side logic without managing servers.</p>
</li>
<li><p><strong>Push Notifications</strong>: Send real-time alerts to users on various devices.</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://backendless.com/">Backendless</a></p>
<h3 id="heading-pricing-3">Pricing</h3>
<p>Backendless offers several plans to suit different needs:</p>
<ul>
<li><p><strong>Free Plan</strong>: Ideal for small projects or learning purposes.</p>
</li>
<li><p><strong>Scale Fixed Plan</strong>: Provides predictable monthly billing with set resource limits.</p>
</li>
<li><p><strong>Scale Variable Plan</strong>: Offers flexibility with usage-based billing, scaling as your app grows.</p>
</li>
<li><p><strong>Backendless Pro</strong>: A self-hosted solution for enterprises requiring unlimited scalability and control.</p>
</li>
</ul>
<p>For more details on Backendless's pricing plans, please visit their <a target="_blank" href="https://backendless.com/pricing/">official pricing plan page</a>.</p>
<h3 id="heading-appwrite"><strong>Appwrite</strong></h3>
<p>Appwrite is an open-source BaaS that provides databases, authentication, file storage, real-time updates, serverless functions, and API management. It supports multiple platforms and offers built-in security and scalability for modern apps.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730036473890_FireShot+Capture+583+-+Appwrite+-+Build+like+a+team+of+hundreds+-+appwrite.io.png" alt="The Graphical Interface of Appwrite" width="600" height="400" loading="lazy"></p>
<h3 id="heading-features-1">Features</h3>
<ul>
<li><p><strong>Authentication</strong>: Secure user login with over 30 methods, including email/password, OAuth, and magic URLs.</p>
</li>
<li><p><strong>Database</strong>: Scalable storage with advanced permissions, custom data validation, and support for relationships.</p>
</li>
<li><p><strong>Functions</strong>: Deploy serverless functions in over 13 languages, with automatic GitHub deployment and custom domain support.</p>
</li>
<li><p><strong>Storage</strong>: Manage and serve files with built-in security and privacy features.</p>
</li>
<li><p><strong>Real-Time</strong>: Subscribe to database events for instant updates.</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://appwrite.io/">Appwrite</a></p>
<h3 id="heading-pricing-4"><strong>Pricing</strong></h3>
<ul>
<li><p><strong>Free</strong> – $0/month (5GB bandwidth, 2GB storage, 750K function runs).</p>
</li>
<li><p><strong>Pro</strong> – Starts at $15/month (more storage, bandwidth, &amp; features).</p>
</li>
<li><p><strong>Scale</strong> – Starts at $599/month (for large-scale projects).</p>
</li>
</ul>
<p>For more details on the pricing plan check their <a target="_blank" href="https://appwrite.io/pricing">official pricing page</a>.</p>
<h3 id="heading-nhost"><strong>Nhost</strong></h3>
<p>Nhost is a full backend platform with a GraphQL API, database, authentication, and storage. It’s easy to set up and great for modern app development.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730036732414_FireShot+Capture+585+-+Nhost_+The+Open+Source+Firebase+Alternative+with+GraphQL+-+nhost.io.png" alt="s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730036732414_FireShot+Capture+585+-+Nhost_+The+Open+Source+Firebase+Alternative+with+GraphQL+-+nhost.io" width="600" height="400" loading="lazy"></p>
<h3 id="heading-nhost-features"><strong>Nhost Features</strong></h3>
<ul>
<li><p><strong>Authentication</strong> – Secure login with email, OAuth, and so on.</p>
</li>
<li><p><strong>Database</strong> – Scalable storage with permissions.</p>
</li>
<li><p><strong>Serverless Functions</strong> – Run backend code without servers.</p>
</li>
<li><p><strong>Storage</strong> – Secure file hosting.</p>
</li>
<li><p><strong>Real-Time</strong> – Instant updates on data changes.</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://nhost.io/">Nhost</a>.</p>
<h3 id="heading-pricing-5"><strong>Pricing</strong></h3>
<ul>
<li><p><strong>Free</strong> – $0/month (basic features for small projects).</p>
</li>
<li><p><strong>Pro</strong> – $25/month (more resources &amp; support).</p>
</li>
<li><p><strong>Dedicated Compute</strong> – $50/month per vCPU/2GB RAM (for scaling apps).</p>
</li>
</ul>
<p>Check out full details here: <a target="_blank" href="https://nhost.io/pricing">Nhost Pricing</a></p>
<h3 id="heading-back4apps"><strong>Back4apps</strong></h3>
<p>Back4App is an open-source BaaS that simplifies backend development. It provides a complete infrastructure for building, hosting, and managing scalable apps. With built-in server-side features, developers can focus on coding without managing servers or databases.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730036859543_FireShot+Capture+587+-+Build+launch+and+scale+applications+faster+than+ever+with+the+power_+-+www.back4app.com.png" alt="The Graphical Interface of Back4apps" width="600" height="400" loading="lazy"></p>
<h3 id="heading-back4app-features"><strong>Back4App Features</strong></h3>
<ul>
<li><p><strong>Database</strong> – Manage data with APIs &amp; a visual editor</p>
</li>
<li><p><strong>Authentication</strong> – Secure user login &amp; roles</p>
</li>
<li><p><strong>Real-Time</strong> – Instant data updates</p>
</li>
<li><p><strong>Push Notifications</strong> – Send alerts to users.</p>
</li>
<li><p><strong>Cloud Functions</strong> – Run custom backend code.</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://www.back4app.com/">Back4apps</a>.</p>
<h3 id="heading-pricing-6"><strong>Pricing</strong></h3>
<ul>
<li><p><strong>Free</strong> – 25K requests, 250MB storage, 1GB transfer/month.</p>
</li>
<li><p><strong>MVP Plan</strong> – For launching small apps.</p>
</li>
<li><p><strong>Dedicated Plan</strong> – For production apps with more resources.</p>
</li>
</ul>
<p>The <strong>MVP Plan</strong> in Back4App refers to a <strong>Minimum Viable Product (MVP) Plan</strong>. It is designed for startups and developers who are launching a small app with essential backend services. This plan provides enough resources to test and validate an idea before scaling up.</p>
<p>While <strong>Dedicated Plan</strong> in Back4App provides a <strong>private server with dedicated resources</strong> for apps that need better performance, security, and scalability. It is ideal for production apps with high traffic or specific infrastructure requirements.</p>
<p>Check out full details here: <a target="_blank" href="https://www.back4app.com/pricing">Back4App Pricing</a>.</p>
<h3 id="heading-aws-amplify"><strong>AWS Amplify</strong></h3>
<p>AWS Amplify is a development platform from Amazon Web Services (AWS). It simplifies building and deploying web and mobile apps. It offers tools and services for developers. They can integrate scalable backends, manage frontends, and add features like authentication, storage, and APIs.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730036938873_FireShot+Capture+588+-+Full+Stack+Development+-+Web+and+Mobile+Apps+-+AWS+Amplify+-+aws.amazon.com.png" alt="The Graphical Interface of Aws Amplify" width="600" height="400" loading="lazy"></p>
<h3 id="heading-aws-amplify-features"><strong>AWS Amplify Features</strong></h3>
<ul>
<li><p><strong>Authentication</strong> – Secure login with email, social sign-in, and multi-factor authentication</p>
</li>
<li><p><strong>Database &amp; API</strong> – Build real-time APIs with AWS databases</p>
</li>
<li><p><strong>Storage</strong> – Manage files and media with Amazon S3</p>
</li>
<li><p><strong>Hosting</strong> – Deploy full-stack apps with continuous deployment</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://aws.amazon.com/amplify/?gclid=Cj0KCQjwpP63BhDYARIsAOQkATZlSP8VJyO8gGZMtrSp7JE6hMJjFPh1Am4F2eQv5Yex_okPLLvWjlUaAgDQEALw_wcB&amp;trk=e37f908f-322e-4ebc-9def-9eafa78141b8&amp;sc_channel=ps&amp;ef_id=Cj0KCQjwpP63BhDYARIsAOQkATZlSP8VJyO8gGZMtrSp7JE6hMJjFPh1Am4F2eQv5Yex_okPLLvWjlUaAgDQEALw_wcB:G:s&amp;s_kwcid=AL!4422!3!647301987559!p!!g!!amplify%20framework!19613610159!148358959649">Aws Amplify</a></p>
<h3 id="heading-pricing-7"><strong>Pricing</strong></h3>
<ul>
<li><p><strong>Free Tier (First 12 months)</strong></p>
<ul>
<li><p>1,000 build minutes/month</p>
</li>
<li><p>5GB storage</p>
</li>
<li><p>15GB bandwidth</p>
</li>
<li><p>500K API requests</p>
</li>
</ul>
</li>
<li><p><strong>Pay-As-You-Go (After Free Tier)</strong></p>
<ul>
<li><p><strong>Build &amp; Deploy</strong> – $0.01 per build minute</p>
</li>
<li><p><strong>Storage</strong> – $0.023 per GB/month</p>
</li>
<li><p><strong>Bandwidth</strong> – $0.15 per GB served</p>
</li>
<li><p><strong>API Requests</strong> – $0.30 per 1M requests</p>
</li>
</ul>
</li>
</ul>
<p>Full details here: <a target="_blank" href="https://aws.amazon.com/amplify/pricing/">AWS Amplify Pricing</a></p>
<h3 id="heading-supabase"><strong>Supabase</strong></h3>
<p>Supabase is an open-source alternative to Firebase. It uses PostgreSQL for its database. It has built-in features like authentication, APIs, and real-time subscriptions.</p>
<p><img src="https://paper-attachments.dropboxusercontent.com/s_C0064052A71C5CFDDDBA59A6AE53132401EA70FC25ACA9B576D0C25C8E9EB8BE_1730037060219_FireShot+Capture+581+-+Supabase+-+The+Open+Source+Firebase+Alternative+-+supabase.com.png" alt="The Graphical Interface of Supabase" width="600" height="400" loading="lazy"></p>
<h3 id="heading-supabase-features"><strong>Supabase Features</strong></h3>
<ul>
<li><p><strong>Database</strong> – PostgreSQL with full SQL support.</p>
</li>
<li><p><strong>Authentication</strong> – Secure login with email, password, and social logins.</p>
</li>
<li><p><strong>Storage</strong> – Store and serve files easily.</p>
</li>
<li><p><strong>Real-Time</strong> – Get instant updates when data changes.</p>
</li>
<li><p><strong>Edge Functions</strong> – Run serverless backend logic.</p>
</li>
</ul>
<p>To learn more, click here: <a target="_blank" href="https://supabase.com/">Supabase</a>.</p>
<h3 id="heading-pricing-8"><strong>Pricing</strong></h3>
<ul>
<li><p><strong>Free</strong> – Great for small projects i.e. projects for learning, and experimentation.</p>
</li>
<li><p><strong>Pro</strong> – Starts at $25/month (includes $10 compute credits).</p>
</li>
<li><p><strong>Team</strong> – Starts at $599/month (for advanced features &amp; support).</p>
</li>
</ul>
<p>Full details here: <a target="_blank" href="https://supabase.com/pricing">Supabase Pricing</a></p>
<h2 id="heading-how-to-get-started-with-baas-quick-example">How to Get Started with BaaS (Quick Example)</h2>
<p>Let’s go through a quick example to get started. In this tutorial, I’ll use Firebase as an example.</p>
<ul>
<li><p>Go to the <a target="_blank" href="https://firebase.google.com/">Firebase website</a> and sign up using your Google account.</p>
</li>
<li><p>After signing in, create a new Firebase project by following the on-screen instructions.</p>
</li>
<li><p>Go to "Authentication" and enable a sign-in method, like email/password or Google login</p>
</li>
<li><p>In "Firestore Database," create a new database for your app's data.</p>
</li>
<li><p>Install Firebase SDK in your project and integrate authentication, databases, and other Firebase services into your app.</p>
</li>
</ul>
<p>For more detailed instructions on setting up Firebase, check out this article: <a target="_blank" href="https://www.freecodecamp.org/news/authenticate-react-app-using-firebase/">How to Authenticate Your React App Using Firebase</a> where I explain each step in depth.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Backend as a Service (BaaS) is ideal for developers. It provides an efficient and cost-effective way to handle backend development tasks. BaaS can speed up your development. It lets you avoid server management. You can then focus on building better apps.</p>
<p>If you're new to backend development, check out the BaaS tools in this article. They can simplify your workflow. Try out BaaS today and take your development to the next level!</p>
<p>Have you tried using BaaS for your applications? Share your experiences!</p>
<p>If you found this article helpful, share it with others who may find it interesting.</p>
<p>Stay updated with my projects by following me on <a target="_blank" href="https://twitter.com/ijaydimples">Twitter</a>, <a target="_blank" href="https://twitter.com/ijaydimples">LinkedIn</a> and <a target="_blank" href="https://github.com/ijayhub">GitHub</a>.</p>
<p>Thank you for reading.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Become a Web Developer – a Beginner's Guide ]]>
                </title>
                <description>
                    <![CDATA[ Are you considering a career in web development? If so, then you are making an excellent choice. Web Development is one of the most in-demand skills in the market in 2024. With over 5.038 billion Internet users, web development has a promising future... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-become-a-web-developer-beginners-guide/</link>
                <guid isPermaLink="false">676884d7626250532f8a0785</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Frontend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kunal Nalawade ]]>
                </dc:creator>
                <pubDate>Sun, 22 Dec 2024 21:29:59 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/505eectW54k/upload/4567a9e14c8e9bac3dc8d6c6a39661f5.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you considering a career in web development? If so, then you are making an excellent choice. Web Development is one of the most in-demand skills in the market in 2024. With over <a target="_blank" href="https://www.webfx.com/web-development/statistics/">5.038 billion Internet users</a>, web development has a promising future.</p>
<p>In this article, I am going to show you the essentials of getting started with web development. We’ll explore key tech stacks, beginner-friendly project ideas, helpful resources, and some additional tips.</p>
<p>Two years ago, I wrote an <a target="_blank" href="https://medium.com/gitconnected/read-this-to-kickstart-your-web-development-journey-26f54b1a4843">article</a> on this topic. Since the demand for web development still remains very high, I am excited to re-visit it with a more detailed guide. So, stick around until the end.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-a-website">What is a Website?</a></p>
<ol>
<li><a class="post-section-overview" href="#heading-frontend-vs-backend-of-a-website">Frontend vs Backend</a></li>
</ol>
</li>
<li><p><a class="post-section-overview" href="#heading-frontend-development">Frontend Development</a></p>
<ol>
<li><p><a class="post-section-overview" href="#heading-html">HTML</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-css">CSS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-javascript">JavaScript</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-learn-frontend-frameworks-and-libraries">Frontend Frameworks and Libraries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-learn-responsive-design">Responsive Design</a></p>
</li>
</ol>
</li>
<li><p><a class="post-section-overview" href="#heading-backend-development">Backend Development</a></p>
<ol>
<li><p><a class="post-section-overview" href="#heading-why-should-you-learn-a-programming-language">Why you should learn a programming language?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-python">Python</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-golang">Golang</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-java">Java</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-javascript-1">JavaScript</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-choose-a-programming-language">How to choose a programming language?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-backend-development-frameworks">Backend Frameworks</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-databases">Databases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-apis">APIs</a></p>
</li>
</ol>
</li>
<li><p><a class="post-section-overview" href="#heading-git-and-github">Git and GitHub</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-build-a-portfolio-of-projects">Build a portfolio of projects</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-deployment-and-hosting-platforms">Deployment and Hosting Services</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-additional-tips">Additional Tips</a></p>
</li>
</ol>
<h2 id="heading-what-is-a-website">What is a Website?</h2>
<p>A web page is a document displayed in a web browser (like Chrome, Firefox, and so on). It consists of text, images, and other interactive elements. And a website is a collection of web pages that are connected to each other via links.</p>
<p>A website runs on a remote computer referred to as a web server, and is accessed via the internet. Some examples of well-known websites are Wikipedia, Amazon, and YouTube.</p>
<p><strong>Note</strong>: When I mention web apps or web applications in this article, I mean the same thing as websites.</p>
<p>A web app has two components, the frontend and the backend. Let’s understand the difference between them.</p>
<h3 id="heading-frontend-vs-backend-of-a-website">Frontend vs Backend of a Website</h3>
<p>The frontend is the user interface (UI) of the website, which is basically what the user sees on their screen.</p>
<p>The backend refers to the server where the main logic of the website is located. It also includes the database, where all the application’s data is stored.</p>
<p>The frontend and the backend communicate by exchanging data. Let’s take an example of a social media app like Instagram.</p>
<p>When you upload a post, the UI sends the post data to the backend, which processes the data and adds it to the database. Then the next time, when you load the site/app, it fetches all your posts from the backend and displays them on the screen.</p>
<p>In the next two sections, I will show how you can start with frontend and backend development.</p>
<h2 id="heading-frontend-development">Frontend Development</h2>
<p>As I mentioned above, frontend development is mainly concerned with the UI – that is, the appearance of the website. To get started with frontend development, you’ll need to learn the following three essentials tools:</p>
<h3 id="heading-html">HTML</h3>
<p>HTML (HyperText Markup Language) is used to write web pages that are displayed by the browser. It defines the structure and content of a web page, making it the backbone of every website.</p>
<p>The content of a web page includes elements such as headings, paragraphs, links, images, lists, and so on. HTML creates and structures all these elements through the use of HTML <em>tags.</em> The browser, in turn, interprets this HTML code and renders it on your screen.</p>
<p>freeCodeCamp’s Responsive Web Design certification in their free curriculum starts off by teaching you HTML basics. You’ll even build your own photo app. So that’s a good place to start and dig deep into HTML.</p>
<p>If you want additional practice, <a target="_blank" href="https://www.w3schools.com/html/">w3schools.com</a> is a helpful resource for beginners as well. It offers clear and step-by-step tutorials for each concept. They also provide an interactive editor for you to practice using HTML tags and see the output web page (as does freeCodeCamp).</p>
<p>Focus on the following areas:</p>
<ul>
<li><p>Creating a simple web page</p>
</li>
<li><p>Using HTML tags to render content</p>
</li>
<li><p>Creating Forms</p>
</li>
</ul>
<h3 id="heading-css">CSS</h3>
<p>While HTML defines the structure of the web page, it is not enough as it just creates a skeletal UI of a web page. It just defines what elements are present on the page, and not how they look.</p>
<p>CSS (Cascading Style Sheets) is used to add visual appeal to the web page. It transforms a simple, plain web page into a properly designed user interface.</p>
<p>Here’s how a website looks with plain HTML:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*SUE5ynYY1Tu5BXOQZCoJtQ.png" alt="1*SUE5ynYY1Tu5BXOQZCoJtQ" width="1400" height="734" loading="lazy"></p>
<p>And this is what it looks like when you add CSS:</p>
<p><img src="https://miro.medium.com/v2/resize:fit:1400/1*9cVIjOqY-sQESGI9qDVw0w.png" alt="1*9cVIjOqY-sQESGI9qDVw0w" width="1400" height="749" loading="lazy"></p>
<p>Much better, right? It actually looks like a proper web page, as compared to the skeletal UI before. This is referred to as “styling” a web page.</p>
<p>CSS styling includes the following:</p>
<ul>
<li><p>Colours, fonts, and element backgrounds</p>
</li>
<li><p>Organising content in various layouts (grid, flex box, and so on)</p>
</li>
<li><p>Spacing, that is margins and paddings</p>
</li>
<li><p>Transitions and Animations (Advanced stuff)</p>
</li>
</ul>
<p>As you continue on in the freeCodeCamp curriculum, you’ll learn CSS as well – so that’s a great way to go.</p>
<p>You can also refer to <a target="_blank" href="https://www.w3schools.com/css/default.asp">w3schools.com</a> for CSS Tutorials. Play around with each CSS property in their interactive editors.</p>
<p><strong>Note:</strong> HTML and CSS are NOT programming languages.</p>
<h3 id="heading-javascript">JavaScript</h3>
<p>HTML and CSS are only able to create static websites – that is, you cannot interact with any of the elements on a web page created with just HTML and CSS. The website does not update or respond to any user interactions like button clicks or dropdown selections.</p>
<p>JavaScript (JS) is a programming language that makes a website dynamic and interactive. It adds the following functionalities to a website:</p>
<ul>
<li><p>Handling user interactions like clicks, hovers, keyboard presses, form filling, and so on.</p>
</li>
<li><p>Updating content dynamically on a web page</p>
</li>
<li><p>Handling form validations and submissions</p>
</li>
<li><p>Interacting with the backend servers</p>
</li>
</ul>
<p>JavaScript has many more capabilities that make your website functional and engaging for end users. As you start your JS learning journey, building strong foundation of the concepts is key. Initially, focus on the following areas:</p>
<ul>
<li><p>Basic JavaScript syntax</p>
</li>
<li><p>JS Functions</p>
</li>
<li><p>Interacting with DOM (Document Object Model)</p>
</li>
<li><p>Event Handling</p>
</li>
<li><p>JS Objects and Arrays</p>
</li>
<li><p>Asynchronous JavaScript</p>
</li>
</ul>
<p>Refer to the following resources for JavaScript:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures-v8/">freeCodeCamp</a> for a free, in-depth, JS curriculum</li>
</ul>
<ul>
<li><p><a target="_blank" href="https://www.w3schools.com/js/default.asp">w3schools.com</a> for basic JavaScript tutorial</p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/js-interview-prep-handbook/">JavaScript Interview Prep Handbook</a> for important JavaScript concepts.</p>
</li>
</ul>
<p>There are a lot of other resources for JavaScript, but I won’t overwhelm you with too many. These two should be enough to get started.</p>
<p>Once you are familiar with HTML, CSS, and JavaScript, you’ll know how to create a simple web page. Keep practicing by building different web pages, such as to-do lists and forms, and try implementing CRUD (Create, Read, Update, Delete) features.</p>
<h3 id="heading-learn-frontend-frameworks-and-libraries">Learn Frontend Frameworks and Libraries</h3>
<p>As your website grows, the JavaScript code becomes more and more complex and harder to maintain. This slows down the development process and makes it really challenging for developers.</p>
<p>To address these issues, you can use frameworks and libraries. Frameworks provide a more structured way to build web apps, encouraging modular design and reusability.</p>
<p>By using frameworks, you can focus on building actual features rather than handling the complexities of JavaScript code, which helps you speed up the development process. So I suggest picking up one JS framework/library to develop bigger projects.</p>
<h4 id="heading-reactjs-a-good-option">React.js – a good option</h4>
<p>React JS is a JavaScript library that makes it easy to create dynamic and interactive web pages. It divides your code into components, making it easy to read and maintain. This reduces code complexity and allows reusability.</p>
<p>React is my personal suggestion since it has a gentler learning curve compared to other frameworks. It is in very high demand among frontend roles, as many web apps are built in React.</p>
<p>To start learning React, your best resource is the <a target="_blank" href="https://react.dev/learn">React Docs</a>. They are very detailed, and include interactive code editors to play around with.</p>
<p>The freeCodeCamp YouTube channel also has some helpful React courses, like <a target="_blank" href="https://www.freecodecamp.org/news/learn-react-2024/">this one from Bob Ziroll</a>, and the Frontend Development Libraries certification has a <a target="_blank" href="https://www.freecodecamp.org/learn/front-end-development-libraries/#react">React section as well</a>.</p>
<p>Apart from React, there are other JavaScript frameworks like Angular, Vue, and the jQuery library. These remain popular as well, and depending on which tools are in demand in your area, you can focus on the one that will meet your needs the best.</p>
<p><strong>Note:</strong> Make sure you learn all the basic JavaScript concepts and understand them fully before jumping into any framework.</p>
<h3 id="heading-learn-responsive-design">Learn Responsive Design</h3>
<p>Before moving on, let’s talk about a fundamental practice in web development.</p>
<p>Responsive design refers to an approach where your design adjusts to fit screens of all sizes, ranging from desktops to tablets and mobiles. A good responsive design drastically reduces the need to write separate code for different screen sizes.</p>
<p>Here’s an interesting fact: <em>mobile phones make up two-thirds of web usage in the entire world.</em> So, to ensure a good user experience, you need to make the website look good on mobile phones.</p>
<p>Learn more about responsive design in this <a target="_blank" href="https://levelup.gitconnected.com/read-this-to-make-your-website-responsive-35af4ab7992b">simple guide</a>, and read more about <a target="_blank" href="https://www.freecodecamp.org/news/responsive-design-best-practices/">some best practices here</a>.</p>
<p>And here are some other resources that can help you on your frontend journey:</p>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn">MDN Docs</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/@WebDevSimplified">WebDevSimplified</a> - YouTube Channel</p>
</li>
</ul>
<h2 id="heading-backend-development">Backend Development</h2>
<p>Backend Development involves building the server-side of web applications. The server-side hosts the business logic of a website, that powers everything behind the scenes. It is also responsible for managing databases and ensuring smooth flow of data between server and the UI.</p>
<p>To dive into backend development, you need to learn a programming language first.</p>
<h3 id="heading-why-should-you-learn-a-programming-language">Why should you learn a programming language?</h3>
<p>Learning a programming language equips you with the foundations to build these server-side applications. Think of a language as a way to tell the server what you want it to do.</p>
<p>A programming language serves as a tool to solve problems and create robust, working applications. These languages have various capabilities for handling tasks like storing and managing data, communicating with the front end, and ensuring application security.</p>
<p>Learning a programming language isn’t just about learning the syntax and writing code. It’s about understanding how to create systems that drive a successful website. So, getting familiar with a programming language is a key part of backend development.</p>
<p>There are a number of programming languages out there, each with its own features. Let’s understand a few options:</p>
<h3 id="heading-python">Python</h3>
<p>Python is one of the preferred choices for backend development because of its simplicity. It has a concise and readable syntax making it very popular. It offers good features for database connections and setting up web servers. Python also has libraries for data science and machine learning.</p>
<p>Python is has a lot of tutorials and good community support, making it easy to get started with. It is beginner friendly, fun to learn and has a high demand.</p>
<p>Refer to the following resources for learning Python:</p>
<ul>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/ultimate-beginners-python-course/">Ultimate Python Beginner’s Course</a> on freeCodeCamp’s YouTube channel</p>
</li>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/python-programming-language-tutorial/">GeeksforGeeks</a> Python Tutorial</p>
</li>
<li><p><a target="_blank" href="https://youtu.be/vLqTf2b6GZw?si=hcggX88jmrVYvpC5">Python Tutorial for Beginners on YouTube</a> (Hindi)</p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/learn/machine-learning-with-python/">Machine Learning with Python</a> – freeCodeCamp certification</p>
</li>
</ul>
<h3 id="heading-golang">Golang</h3>
<p>Golang (Go) is increasing in popularity because of its simplicity and efficiency. Go code executes quickly and efficiently, making it a good option for high performance needs. This also leads to faster development time. Go also has excellent support for <a target="_blank" href="https://gowthamy.medium.com/concurrent-programming-introduction-1b6eac31aa66">concurrency</a>, which leads to efficient processing.</p>
<p>Go is beginner-friendly and has a clean and concise syntax, making it easy to read and maintain. It also has an extensive standard library offering a many built-in functions and tools, so it’s easy to set up a project without much hassle.</p>
<p>Go is growing in popularity because of its efficiency, and many companies are adopting Go for their projects. This has lead to an increasing demand for Golang developers and it’s expected to go up.</p>
<p>Go offers plenty of resources and a growing community for beginners. To get started with Go, refer to the following resources:</p>
<ul>
<li><p><a target="_blank" href="https://go.dev/tour/welcome/1">Tour of Go</a> – Interactive Learning with basic Golang concepts</p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/go-beginners-handbook/">Golang Handbook</a> from Flavio Copes</p>
</li>
<li><p><a target="_blank" href="https://go.dev/doc/">Go Docs</a> – Very detailed</p>
</li>
</ul>
<h3 id="heading-java">Java</h3>
<p>Java is an <a target="_blank" href="https://medium.com/gitconnected/come-and-join-the-beautiful-world-of-java-9cedc815bafa">Object-Oriented Programming</a> (OOP) language, widely used for backend development. Java is known for its security and robustness, making it a preferred choice for applications that require high reliability such as financial and healthcare systems. Java also offers a great support for concurrency.</p>
<p>Java is a good option for beginners as it has extensive resources and a large developer community. This includes plenty of tutorials and detailed documentation to make life easier for beginners as well as experienced developers.</p>
<p>Java has been around for a while, and many existing systems and enterprise applications currently run on Java. So, there is a huge demand for Java developers among big enterprises.</p>
<p>Lastly, the concepts that you learn while coding in Java stick with you and make you a better developer, even if you switch languages going forward.</p>
<p>The following resources can help you get started with Java:</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=A74TOX803D0">Java Programming for Beginners on freeCodeCamp.org</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/object-oriented-programming-concepts-java/">Objects-Oriented Programming in Java</a></p>
</li>
</ul>
<h3 id="heading-javascript-1">JavaScript</h3>
<p>We already know what JavaScript offers to frontend, but it can also be used for backend development through NodeJS.</p>
<p>NodeJS is a run time environment that allows you to run JS code on the server side. This makes it possible to use JavaScript for both the frontend and the backend.</p>
<p>NodeJS follows an event-driven architecture and asynchronous programming, which enables it to handle multiple tasks without stopping execution for a single one (non-blocking I/O). Node is single threaded, so instead of creating multiple threads to handle tasks, it executes them one by one asynchronously by queuing tasks.</p>
<p>Node also follows a modular architecture, meaning you can break your application into smaller, manageable components. It also includes <a target="_blank" href="https://docs.npmjs.com/about-npm">NPM</a> (Node Package Manager) which provides access to thousands of open-source libraries to add functionality like routing, authentication, or database handling.</p>
<p>Why use Node?</p>
<ul>
<li><p>This is a very good option if you are already familiar with JavaScript, as you don’t need to learn any other language.</p>
</li>
<li><p>Node is fast and efficient, making it easy if you want to set up a small server quickly.</p>
</li>
<li><p>Node also has a large ecosystem of libraries through NPM.</p>
</li>
</ul>
<p>However, Node is not ideal for CPU-intensive tasks as they can block the main thread, since it’s single threaded.</p>
<h3 id="heading-how-to-choose-a-programming-language">How to choose a programming language?</h3>
<p>With so many options available, it may feel confusing to choose the right one for you. Each language has its own capabilities and no language is objectively better than the other.</p>
<p>Python and Golang are very beginner-friendly with simple syntax. So, if you value a gentle learning curve, then these two are good options. Java is known for its reliability and robustness, with a lot of enterprise-level applications built using Java.</p>
<p>As for the job opportunities, there’s <a target="_blank" href="https://codeop.tech/blog/programming-languages-in-demand/">high demand</a> for each of the above languages, so you can choose any one you want. The most important thing is to develop your problem solving skill and understand how reliable software is built.</p>
<p>The choice of language doesn’t really matter in the long run, since the core fundamentals remain the same. So, my advice is to pick any language, learn its syntax and core capabilities, and start solving problems. You can start with the following:</p>
<ul>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/how-to-start-learning-dsa/">Learn Data Structures and Algorithms</a></p>
</li>
<li><p><a target="_blank" href="https://leetcode.com/discuss/study-guide/623011/A-guide-for-dummies-\(like-me\)">Start solving problems on LeetCode</a></p>
</li>
<li><p>Learn language specific frameworks and develop projects (Upcoming section)</p>
</li>
</ul>
<h3 id="heading-backend-development-frameworks">Backend Development Frameworks</h3>
<p>Programming languages alone are not enough to create robust and secure applications. Frameworks, built on the capabilities of these languages, allow you to create these powerful applications. By providing additional functionalities like routing and database handling, they serve as a platform to put your coding skills to the test and also make the development process faster.</p>
<p>Depending on your language of choice, you can learn the following frameworks:</p>
<ul>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Introduction">Django</a> and <a target="_blank" href="https://www.geeksforgeeks.org/python-introduction-to-web-development-using-flask/">Flask</a> – Python Based Frameworks</p>
</li>
<li><p><a target="_blank" href="https://spring.io/projects/spring-boot">Java Spring Boot</a></p>
</li>
<li><p><a target="_blank" href="https://gin-gonic.com/docs/introduction/">Gin</a> – Golang framework (You can create a simple Golang application without using a framework)</p>
</li>
</ul>
<p>Read more about them if you are interested.</p>
<h3 id="heading-databases">Databases</h3>
<p>A database is a structured collection of data and is a crucial part of backend development. It plays an important role in storing and managing the application’s data.</p>
<p>Databases are broadly categorised into two types:</p>
<ul>
<li><p><strong>Relational Databases</strong> use tables to store data and define relationships between those tables. Examples are <a target="_blank" href="https://www.geeksforgeeks.org/what-is-mysql/">MySQL</a>, <a target="_blank" href="https://www.postgresql.org/about/">PostgreSQL</a>, <a target="_blank" href="https://www.simplilearn.com/tutorials/sql-tutorial/what-is-sqlite">SQLite</a>.</p>
</li>
<li><p><strong>Non-Relational Databases (NoSQL)</strong> are designed to handle unstructured or semi-structured data and are often used for hierarchical or document-based data storage. Examples are <a target="_blank" href="https://www.geeksforgeeks.org/what-is-mongodb-working-and-features/">MongoDB</a> and <a target="_blank" href="https://www.geeksforgeeks.org/apache-cassandra-nosql-database/">Cassandra</a>.</p>
<ul>
<li><p><strong>MongoDB</strong>: A popular NoSQL database for flexible and scalable data storage.</p>
</li>
<li><p><strong>Cassandra</strong>: Suitable for handling large amounts of distributed data.</p>
</li>
</ul>
</li>
</ul>
<p>To begin with relational databases, <a target="_blank" href="https://www.freecodecamp.org/news/learn-sql-free-relational-database-courses-for-beginners/">learn SQL (Structured Query Language)</a>. SQL is used to write queries that perform various operations on the data, such as:</p>
<ul>
<li><p><strong>Creating</strong> tables and defining their structure.</p>
</li>
<li><p><strong>Reading</strong> data using SELECT statements.</p>
</li>
<li><p><strong>Updating</strong> existing records.</p>
</li>
<li><p><strong>Deleting</strong> unnecessary or outdated data.</p>
</li>
</ul>
<p>Refer to the following resources to learn SQL:</p>
<ul>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/a-beginners-guide-to-sql/">Full handbook on SQL</a></p>
</li>
<li><p><a target="_blank" href="https://www.w3schools.com/sql/">w3schools.com</a></p>
</li>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/sql-tutorial/">GeeksforGeeks</a> – Great resource to learn about database concepts</p>
</li>
</ul>
<p>Once you are familiar with basic SQL syntax and are able to write queries, explore <a target="_blank" href="https://www.geeksforgeeks.org/dbms/">DBMS (DataBase Management System)</a> concepts. These help you understand how databases are designed, managed, and optimised.</p>
<p>As a beginner, I recommend starting with relational databases because they provide a solid foundation in DBMS concepts involving tables and relationships between them. They are much more widely used among enterprises and learning their concepts can benefit you a lot.</p>
<p>These concepts might take some time to study, but don't worry about it. Take your time and keep working on the development stuff in parallel. You'll understand these concepts better as you gain more experience working with databases.</p>
<h3 id="heading-apis">APIs</h3>
<p>APIs (Application Programming Interfaces) are an essential part of backend development as they expose the backend logic to the outside world. APIs are a way for two different applications to communicate with each other. In the context of web development, the frontend interacts with the backend services through APIs.</p>
<p>When you build a web application, the frontend often needs to send and receive data from the backend. Let’s take an example of login functionality. When a user logs in, the frontend sends their credentials to the backend through an API call. The backend verifies this information and responds with the result.</p>
<p>To see these API calls, visit any website and open the Network Tab in Developer Tools. Interact with the website, or just reload the page, you’ll see the API calls being made as you use the website.</p>
<p>Read the following articles to understand more about APIs:</p>
<ul>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/what-is-an-api/">GeeksforGeeks - What is an API?</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/apis-for-beginners/">Full beginner-friendly course on APIs</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/how-apis-work/">How does an API work?</a></p>
</li>
</ul>
<p>At this point, you know how to start with both frontend and backend development. If you've reached this stage, congratulations! You've completed most of the hard work. But there’s one more thing you need to learn before you start developing projects.</p>
<h2 id="heading-git-and-github">Git and GitHub</h2>
<p>Git is a version control system that keeps track of changes in a software project. It allows multiple people to work on the project without directly interfering with each other’s work.</p>
<p>GitHub is a remote repository system based on Git. It is like social media, but for your code. GitHub encourages collaboration among developers and keeps track of everyone’s contributions.</p>
<p>GitHub lets you share your project code and view other developers' code, too. This facilitates increased collaboration and learning. I strongly recommend learning Git, especially at the beginning of your development journey.</p>
<p>To get started with Git and GitHub, refer to the following articles:</p>
<ul>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/learn-the-basics-of-git-in-under-10-minutes-da548267cc91/">Learn the Basics of Git in Under 10 Minutes</a></p>
</li>
<li><p><a target="_blank" href="https://www.freecodecamp.org/news/gitting-things-done-book/">Full book on Git and GitHub + version control basics</a></p>
</li>
<li><p><a target="_blank" href="https://docs.github.com/en/get-started/start-your-journey">Getting Started with GitHub</a></p>
</li>
</ul>
<h2 id="heading-build-a-portfolio-of-projects">Build a Portfolio of Projects</h2>
<p>Now, you are ready to start working on projects. A strong portfolio of projects is essential for showcasing your skills. It also helps you apply what you have learned so far and improves your problem-solving skills.</p>
<p>Consider the following project ideas:</p>
<ul>
<li><p>Todo App</p>
</li>
<li><p>E-Commerce App</p>
</li>
<li><p>Personal Portfolio website</p>
</li>
<li><p>Weather App – Use a public API and create a simple UI</p>
</li>
<li><p>Expense Tracker</p>
</li>
</ul>
<p>You can research more about these ideas and start with some basic features that come to mind. Build either the frontend, the backend, or both, depending on your goals. Share your projects on GitHub to increase their visibility.</p>
<p>Check out <a target="_blank" href="https://www.geeksforgeeks.org/web-development-projects/">GeeksforGeeks</a> for more project ideas.</p>
<h2 id="heading-deployment-and-hosting-platforms">Deployment and Hosting Platforms</h2>
<p>Once you have developed a web project, you can choose to release it to the public. This means that your website will be available on the internet for the public to use. How exciting is that!</p>
<p>Let’s understand the above terms. <strong>Deployment</strong> refers to the process of uploading your application to a remote system or a server in order to make it live and available to users. <strong>Hosting</strong> is like renting a space on the Internet for storing your application code. It provides a space to keep your website’s data on the server and displays your website on the internet.</p>
<p>Deploying and Hosting an application mainly follows these steps:</p>
<ul>
<li><p>The application code is written, tested locally, and optimised for production</p>
</li>
<li><p>The required configurations and secrets (passwords, API keys, and so on) are written as environment variables</p>
</li>
<li><p>The code is pushed to a version control system like GitHub or GitLab</p>
</li>
<li><p>The code is scanned for any security vulnerabilities and automated tests are run</p>
</li>
<li><p>Hosting platforms pull the code from these repositories and make it accessible on the internet.</p>
</li>
</ul>
<p>Hosting services like <a target="_blank" href="https://www.netlify.com/blog/2016/09/29/a-step-by-step-guide-deploying-on-netlify/">Netlify</a>, <a target="_blank" href="https://pages.github.com/">GitHub Pages</a>, and <a target="_blank" href="https://www.heroku.com/">Heroku</a> offer free and paid services and are easy to use for beginners. Netlify only supports frontend applications while Heroku is good for backend and full stack applications with easy integration of databases. GitHub Pages lets you host right from your repository.</p>
<p>Releasing your website to the public is a great opportunity to showcase your work to recruiters and potential collaborators.</p>
<h2 id="heading-additional-tips">Additional Tips</h2>
<ol>
<li><p>Don't spend too much time on tutorials, as you might get stuck in "tutorial hell." Tutorials are important for understanding core concepts, but real learning happens when you work hands-on. So start building as soon as you can, even if it’s just small projects at first.</p>
</li>
<li><p>JavaScript might seem overwhelming at first, but start small and practice regularly. Don’t rush to learn multiple things at once, tackle one concept at a time and practice through code for better understanding.</p>
</li>
<li><p>Experiment with different frameworks initially to find one that works for you. Once you choose a framework, stick with it until you learn it well.</p>
</li>
<li><p>Ensure that your programming language concepts are clear before jumping into any framework.</p>
</li>
<li><p>If you feel that a programming language is not working for you, you can switch to a different one, the core fundamentals remain the same.</p>
</li>
<li><p>As a beginner, it's important to have a basic understanding of both the frontend and the backend. Later, you can choose to specialise in one or you can choose to focus on both, becoming a "full stack" developer.</p>
</li>
<li><p>You will face challenges at first, so don't get discouraged. Keep practicing, and you will get better over time.</p>
</li>
<li><p>If you are stuck on any issue, use Chat GPT, Google Search, forums and developer communities, and Stack Overflow as much as possible. I am always available if you need any help.</p>
</li>
<li><p>Lastly, stay updated with the latest trends and technologies in web development. Always look for new or improved ways to solve problems. Learning never stops!</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Web Development is divided into two parts: frontend and backend development. The frontend is concerned with the website’s appearance while the backend focuses on the server-side logic and databases.</p>
<p>HTML, CSS, and JavaScript are the essentials in frontend development and form the backbone of a website. In backend development, learning a programming language like Python or Java is key. Both frontend and backend frameworks provide additional capabilities and make the development process faster.</p>
<p>Git is a must-have skill as it allows you to share your work and collaborate with other developers. Building a portfolio of projects and sharing on GitHub showcases your work and makes you a better developer. Lastly, utilise deployment platforms as they make your website available to the general public.</p>
<p>That’s it for today! I hope this article helps you start your web development journey. Let me know what you think. Your feedback is always appreciated!</p>
<p>Connect with me on Twitter for more updates and discussions. If you have any questions or clarifications, feel free to reach out. Thank you for reading, and I look forward to seeing you next time!</p>
<h3 id="heading-references"><strong>References:</strong></h3>
<ul>
<li><p><a target="_blank" href="https://www.geeksforgeeks.org/can-start-learn-web-development/">How to become a web developer</a></p>
</li>
<li><p><a target="_blank" href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Getting_started/Your_first_website">Building your first website</a></p>
</li>
<li><p><a target="_blank" href="https://medium.com/shecodeafrica/getting-started-with-backend-engineering-a-beginners-guide-2426759238ea">Getting started with backend engineering</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/watch?v=CWAi_2oLhYg">Developer roadmap</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Key Golang Concepts You Should Learn as a Beginner Go Developer ]]>
                </title>
                <description>
                    <![CDATA[ Learning new programming concepts can be hard. So you'll need a guide or a roadmap to help you navigate through the process. Learning Golang is no exception. And as a beginner, you'll need to work diligently to learn the fundamental building blocks o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/key-golang-concepts-for-beginner-go-devs/</link>
                <guid isPermaLink="false">6733b552ba5d0212f3eab6e1</guid>
                
                    <category>
                        <![CDATA[ golang ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Beginner Developers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Temitope Oyedele ]]>
                </dc:creator>
                <pubDate>Tue, 12 Nov 2024 20:06:42 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731435098075/7fee649f-911d-4537-a613-1fa12824a011.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Learning new programming concepts can be hard. So you'll need a guide or a roadmap to help you navigate through the process.</p>
<p>Learning Golang is no exception. And as a beginner, you'll need to work diligently to learn the fundamental building blocks of the language. These key introductory concepts are important as they help you lay the groundwork for more complex development.</p>
<p>In this article, we will explore the main parts of Go that every beginner should learn to build a strong foundation in the language. So if you’re just starting out, this guide will help you solidify your knowledge and start building projects that’ll make you more confident coding in Golang.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-variables-and-datatypes">Variables and Datatypes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-control-structures">Control Structures</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-ifelse-statements">1. If/Else Statements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-switch-statements">2. Switch Statements</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-for-loops">3. For Loops</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-functions">Functions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pointers">Pointers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-error-handling">Error Handling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-goroutines-and-concurrency">Goroutines and Concurrency</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-structs-and-inheritance">Structs and Inheritance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-go-standard-library">Go Standard Library</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-accessing-and-using-a-package-from-the-standard-library">Accessing and Using a Package from the Standard Library</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-testing-in-go">Testing in Go</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-thats-a-wrap">That’s a Wrap!</a></p>
</li>
</ul>
<h2 id="heading-variables-and-datatypes">Variables and Datatypes</h2>
<p>Variables in Go are used to store and manage data within a program. They act as containers that hold values of specific types. Variables allow you to retrieve and manipulate stored information.</p>
<p>Below is an example of using variables in Go:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>{
 <span class="hljs-comment">// Variables</span>
    <span class="hljs-keyword">var</span> age <span class="hljs-keyword">int</span> = <span class="hljs-number">30</span>
    <span class="hljs-keyword">var</span> name <span class="hljs-keyword">string</span> = <span class="hljs-string">"John"</span>
    salary := <span class="hljs-number">50000.50</span> <span class="hljs-comment">// Short variable declaration(only to be used inside a function</span>
  fmt.Println(age)
  fmt.Println(name)
   fmt.Println(salary)
}
</code></pre>
<p>To learn more about variables, you can check out <a target="_blank" href="https://www.freecodecamp.org/news/variables-and-constants-in-go/">my tutorial on them here</a>.</p>
<p>On the other hand, data types define the kind of data a variable can hold. Since Go is a statically typed language, it requires you to specify the data type of each variable.</p>
<p>Some of the main data types in Go include:</p>
<ul>
<li><p><strong>Boolean</strong>: Represents a true or false value. It's used for logical decisions in the program.</p>
</li>
<li><p><strong>Number</strong>: Includes integer types (like <code>int</code>, <code>int32</code>, <code>int64</code>) and floating-point types (like <code>float32</code>, <code>float64</code>) to store whole numbers and decimal values.</p>
</li>
<li><p><strong>String</strong>: Represents a sequence of characters (text). It’s used to store words, phrases, or any text-based data.</p>
</li>
<li><p><strong>Array</strong>: A collection of fixed-size elements of the same type. Arrays allow you to store multiple values in a single variable.</p>
</li>
<li><p><strong>Slice</strong>: Similar to arrays, but with a dynamic size. Slices are more commonly used in Go since they offer greater flexibility.</p>
</li>
<li><p><strong>Map</strong>: A collection of key-value pairs. Maps are used when you want to associate values with specific keys for fast lookup.</p>
</li>
<li><p><strong>Struct</strong>: A way to group related data together. Structs allow you to define custom data types with multiple fields, each of a different type.</p>
</li>
<li><p><strong>Pointer</strong>: Holds the memory address of another variable, allowing for more efficient memory manipulation in certain cases.</p>
</li>
</ul>
<p>Below is an example showing how some of these data types work:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {

    <span class="hljs-comment">// Data Types</span>
    <span class="hljs-keyword">var</span> isEmployed <span class="hljs-keyword">bool</span> = <span class="hljs-literal">true</span> <span class="hljs-comment">// boolean</span>
    <span class="hljs-keyword">var</span> count <span class="hljs-keyword">int</span> = <span class="hljs-number">42</span> <span class="hljs-comment">// integer</span>
    <span class="hljs-keyword">var</span> greeting <span class="hljs-keyword">string</span> = <span class="hljs-string">"Hello, Go!"</span> <span class="hljs-comment">// string</span>

    <span class="hljs-comment">// Struct</span>
    <span class="hljs-keyword">type</span> Rectangle <span class="hljs-keyword">struct</span> {
        width  <span class="hljs-keyword">float64</span>
        height <span class="hljs-keyword">float64</span>
    }
    rect := Rectangle{width: <span class="hljs-number">10.5</span>, height: <span class="hljs-number">5.2</span>}

    fmt.Println(<span class="hljs-string">"Is Employed:"</span>, isEmployed)
    fmt.Println(<span class="hljs-string">"Count:"</span>, count)
    fmt.Println(<span class="hljs-string">"Greeting:"</span>, greeting)
    fmt.Println(<span class="hljs-string">"Numbers:"</span>, numbers)
    fmt.Printf(<span class="hljs-string">"Rectangle: width = %.2f, height = %.2f\n"</span>, rect.width, rect.height)

}
</code></pre>
<p>In this example, we demonstrate the usage of several data types:</p>
<ol>
<li><p><code>bool</code>: The <code>isEmployed</code> variable is declared as a <code>bool</code> and assigned the value <code>true</code>.</p>
</li>
<li><p><code>int</code>: The <code>count</code> variable is declared as an <code>int</code> and assigned the value <code>42</code>.</p>
</li>
<li><p><code>string</code>: The <code>greeting</code> variable is declared as a <code>string</code> and assigned the value <code>"Hello, Go!"</code>.</p>
</li>
<li><p><code>struct</code>: We define a new data type called <code>Rectangle</code> that has two fields: <code>width</code> and <code>height</code>, both of which are <code>float64</code>. We then create a new instance of <code>Rectangle</code> and assign values to its fields.</p>
</li>
</ol>
<p>Variables and data types form the basis of programming in Go. These concepts are essential building blocks that you'll use in almost every program you write. They allow you to store, manipulate, and organize data effectively.</p>
<p>With a strong command of variables and data types, you'll also be better equipped to tackle more advanced Go concepts and write robust, efficient code as you progress in your learning journey.</p>
<h2 id="heading-control-structures">Control Structures</h2>
<p>In Go, control structures are simply constructs that control the flow of execution in a program. They allow you to perform different actions based on conditions or repeatedly execute a block of code.</p>
<p>Some of the main control structures in Go include:</p>
<h3 id="heading-1-ifelse-statements">1. If/Else Statements</h3>
<p>The <a target="_blank" href="https://go.dev/tour/flowcontrol/7">if/else</a> statement in Go executes a block of code based on a condition. If the condition returns true, the code inside the <code>if</code> block is performed. If the condition returns false, the <code>else</code> block (if any) is executed.</p>
<p>For example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    x := <span class="hljs-number">10</span>
    <span class="hljs-keyword">if</span> x &gt; <span class="hljs-number">5</span> {
        fmt.Println(<span class="hljs-string">"x is greater than 5"</span>)
    } <span class="hljs-keyword">else</span> {
        fmt.Println(<span class="hljs-string">"x is 5 or less"</span>)
    }
}
</code></pre>
<p>In the code above, if x is greater than 5, the first block is executed. Otherwise, the <code>else</code> block runs.</p>
<h3 id="heading-2-switch-statements">2. Switch Statements</h3>
<p>The <a target="_blank" href="https://go.dev/tour/flowcontrol/9">switch statement</a> is a multi-directional branch that allows you to execute different blocks of code depending on the value of an expression. It’s easier to read than multiple if/else statements.</p>
<p>For example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    day := <span class="hljs-string">"Monday"</span>
    <span class="hljs-keyword">switch</span> day {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"Monday"</span>:
        fmt.Println(<span class="hljs-string">"Start of the week"</span>)
    <span class="hljs-keyword">case</span> <span class="hljs-string">"Friday"</span>:
        fmt.Println(<span class="hljs-string">"Almost weekend"</span>)
    <span class="hljs-keyword">default</span>:
        fmt.Println(<span class="hljs-string">"It's another day"</span>)
    }
}
</code></pre>
<p>In the code above, the output will be "Start of the week" because the <code>day</code> variable matches the <code>Monday</code> case.</p>
<h3 id="heading-3-for-loops">3. For Loops</h3>
<p>Go only has one looping construct, the <a target="_blank" href="https://go.dev/tour/flowcontrol/1">for loop</a>. It can be used in various forms: traditional loops, range-based loops (to iterate over slices, maps, and so on), and infinite loops.</p>
<p>Below is an example of a traditional loop:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">5</span>; i++ {
        fmt.Println(i)
    }
}
</code></pre>
<p>In the code above, the loop prints the numbers 0 through 4.</p>
<p>The range based loop provides a simplified way for iteration on slices, maps, and others. It makes it easier to access each element directly without needing to manually handle index or length checks. The loop automatically provides both the index and the value during each iteration, improving readability and reducing the chance of off-by-one errors or other indexing issues.</p>
<p>Below is an example of a range-based loop:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    nums := []<span class="hljs-keyword">int</span>{<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>}
    <span class="hljs-keyword">for</span> i, num := <span class="hljs-keyword">range</span> nums {
        fmt.Println(i, num)
    }
}
</code></pre>
<p>In the code above, the <code>for</code> loop is used to iterate over the <code>nums</code> slice. The <code>range</code> keyword returns both the index and the value of each element in the slice. This makes it easy to process all elements of a slice without needing a counter variable.</p>
<h2 id="heading-functions">Functions</h2>
<p>A <a target="_blank" href="https://go.dev/tour/basics/4">function</a> in Go is a block of code that performs a specific task. Functions help you organize code by allowing you to construct reusable code logic, which is easier to maintain and understand.</p>
<p>Below is an example of a function that adds two numbers:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">add</span><span class="hljs-params">(a <span class="hljs-keyword">int</span>, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">return</span> a + b
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    result := add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>)
    fmt.Println(<span class="hljs-string">"Result:"</span>, result)
}
</code></pre>
<p>Here, we have a simple function called <code>add</code> that takes two integer parameters (<code>a</code> and <code>b</code>) and returns their sum, which is also an integer type. The function is then called inside the <code>main</code> function which prints the result.</p>
<p>Functions are the foundation of Go programs, and understanding their structure and capabilities is critical.</p>
<h2 id="heading-pointers">Pointers</h2>
<p>In Go, a <a target="_blank" href="https://go.dev/tour/moretypes/1">pointer</a> is a variable that stores the memory address of another variable. A pointer "points to" the region in memory where the actual value is stored rather than retaining the value itself.</p>
<p>Pointers are useful when you need to pass references to large structures or when you want to modify a variable's value from inside a function. They are also critical for memory management.</p>
<p>Below is a basic example that illustrates how pointers work in Go:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">var</span> num <span class="hljs-keyword">int</span> = <span class="hljs-number">10</span>

    <span class="hljs-keyword">var</span> ptr *<span class="hljs-keyword">int</span> = &amp;num

    fmt.Println(<span class="hljs-string">"Value of num:"</span>, num)      
    fmt.Println(<span class="hljs-string">"Pointer address:"</span>, ptr)   
    fmt.Println(<span class="hljs-string">"Value at pointer:"</span>, *ptr)

    *ptr = <span class="hljs-number">20</span>
    fmt.Println(<span class="hljs-string">"Updated value of num:"</span>, num) 
}
</code></pre>
<p>In the example above, we first declare a variable <code>num</code> and assign it the value of 10. We then create a pointer <code>ptr</code> that stores the memory address of <code>num</code> (using <code>&amp;num</code>) and then print it out to see it. To access the stored pointer value, we use the <code>*ptr</code>. We then modify the value of <code>num</code> through the pointer by setting <code>*ptr</code> to 20, which directly changes <code>num</code> to 20.</p>
<p>This demonstrates how pointers allow you to access and modify variables via their memory addresses, which is useful for more efficient memory handling and function parameter passing in Go.</p>
<p>To get a better understanding of what pointers are, you can <a target="_blank" href="https://dev.to/oyedeletemitope/understanding-pointers-in-go-1fa6">check out my article on them here</a>.</p>
<h2 id="heading-error-handling">Error Handling</h2>
<p>In order to write robust and build reliable applications, you’ll need to learn about <a target="_blank" href="https://go.dev/blog/error-handling-and-go">error handling</a>. Compared to other programming languages, Go takes a unique approach to error handling, encouraging you to handle problems explicitly and immediately rather than relying on exceptions.</p>
<p>In Go, errors are treated as values, which means they are returned from functions just like any other value and must be handled by the developer. This approach helps to promote clarity and also ensures that potential issues are dealt with at the point where they occur.</p>
<p>Below is some example code to illustrate basic error handling in Go:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"errors"</span>
    <span class="hljs-string">"fmt"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">divide</span><span class="hljs-params">(a, b <span class="hljs-keyword">float64</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">float64</span>, error)</span></span> {
    <span class="hljs-keyword">if</span> b == <span class="hljs-number">0</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, errors.New(<span class="hljs-string">"cannot divide by zero"</span>)
    }
    <span class="hljs-keyword">return</span> a / b, <span class="hljs-literal">nil</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    result, err := divide(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>)
    <span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> {
        fmt.Println(<span class="hljs-string">"Error:"</span>, err)
    } <span class="hljs-keyword">else</span> {
        fmt.Println(<span class="hljs-string">"Result:"</span>, result)
    }
}
</code></pre>
<p>In the code above, we have a <code>divide</code> function that takes two numbers and returns both a result and an error. If the second number is zero, an error is returned because division by zero is not allowed.</p>
<p>We also have a <code>main</code> function where we call divide and check if an error occurred by examining the <code>err</code> value. If an error is present, we handle it by printing an error message. Otherwise, we print the result.</p>
<p>This approach to error handling in Go ensures that errors are caught and dealt with right away, making the program more reliable and easier to troubleshoot.</p>
<h2 id="heading-goroutines-and-concurrency">Goroutines and Concurrency</h2>
<p><a target="_blank" href="https://go.dev/tour/concurrency/1">Goroutines</a> and concurrency are concepts that let your code efficiently execute multiple tasks in parallel.</p>
<p>A goroutine is a function that runs concurrently with other functions. Goroutines are incredibly lightweight, with a small memory footprint, allowing you to run thousands (or even millions) of goroutines simultaneously without overwhelming system resources.</p>
<p>Concurrency, on the other hand, refers to a program's capacity to handle numerous tasks at the same time. It does not necessarily imply that the tasks are executing concurrently (which is parallelism) but rather that they are making progress independently.</p>
<p>Let’s look at an example code to illustrate these concepts:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"fmt"</span>
    <span class="hljs-string">"time"</span>
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">printNumbers</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">for</span> i := <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">5</span>; i++ {
        fmt.Println(i)
        time.Sleep(<span class="hljs-number">1</span> * time.Second)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">printLetters</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">for</span> i := <span class="hljs-string">'A'</span>; i &lt;= <span class="hljs-string">'E'</span>; i++ {
        fmt.Printf(<span class="hljs-string">"%c\n"</span>, i)
        time.Sleep(<span class="hljs-number">1</span> * time.Second)
    }
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {

    <span class="hljs-keyword">go</span> printNumbers()  <span class="hljs-comment">// This runs concurrently</span>
    <span class="hljs-keyword">go</span> printLetters()  <span class="hljs-comment">// This runs concurrently</span>

    <span class="hljs-comment">// Wait for goroutines to finish</span>
    time.Sleep(<span class="hljs-number">6</span> * time.Second)
    fmt.Println(<span class="hljs-string">"All tasks completed."</span>)
}
</code></pre>
<p>In the code above, we create two functions, <code>printNumbers</code> and <code>printLetters</code>. One prints numbers from 1 to 5, and the other prints letters from 'A' to 'E'. We launch these functions as <strong>goroutines</strong> by adding the <code>go</code> keyword before calling them in the <code>main</code> function.</p>
<p><strong>Goroutines</strong> are lightweight threads that allow functions to run concurrently. This means both <code>printNumbers()</code> and <code>printLetters()</code> can execute at the same time without waiting for each other to complete. The key concept here is <strong>concurrency</strong>, where multiple tasks (like printing numbers and letters) make progress independently, even though they don't necessarily run in parallel on separate cores.</p>
<p>In this case, both goroutines sleep for one second between prints, but because they are running concurrently, the numbers and letters can be printed almost simultaneously without blocking each other’s execution.</p>
<p>To ensure the program doesn’t exit before the goroutines complete their work, we add a <code>time.Sleep(6 * time.Second)</code> in the <code>main</code> function. This gives enough time for both goroutines to finish printing before the program terminates.</p>
<p>This example illustrates Go's powerful concurrency model through goroutines, enabling efficient multitasking without the complexity of traditional threading.</p>
<p>To dive deeper into goroutines and concurrency, <a target="_blank" href="https://www.freecodecamp.org/news/author/CaesarSage/"><strong>Destiny Erhabor</strong></a> did a fine job in explaining what they are in <a target="_blank" href="https://www.freecodecamp.org/news/how-to-handle-concurrency-in-go/">his article here</a>.</p>
<h2 id="heading-structs-and-inheritance">Structs and Inheritance</h2>
<p>In Go, a <code>struct</code> is a composite data type that organizes variables (fields) into a single type. These fields can include a variety of data types, making structs suitable for describing complex data structures. Structs in Go function similarly to classes in other programming languages but without the methods of inheritance.</p>
<p>Let’s start with an example of a struct:</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    Name <span class="hljs-keyword">string</span>
    Age  <span class="hljs-keyword">int</span>
}
</code></pre>
<p>In this example, <code>Person</code> is a struct with two fields: <code>Name</code> which is a <code>string</code> and <code>Age</code> which is an <code>int</code>. You can create an instance of this struct like so:</p>
<pre><code class="lang-go">p := Person{Name: <span class="hljs-string">"Alice"</span>, Age: <span class="hljs-number">30</span>}
fmt.Println(p.Name)  <span class="hljs-comment">// Output: Alice</span>
</code></pre>
<p>Go does not have traditional <strong>inheritance</strong> like some object-oriented languages where one class inherits fields and methods from another. Instead, Go uses <strong>composition</strong>, which allows you to embed one <code>struct</code> inside another.</p>
<p>Here’s an example code of struct composition:</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Employee <span class="hljs-keyword">struct</span> {
    Person
    Position <span class="hljs-keyword">string</span>
}

e := Employee{
    Person:   Person{Name: <span class="hljs-string">"Bob"</span>, Age: <span class="hljs-number">25</span>},
    Position: <span class="hljs-string">"Developer"</span>,
}

fmt.Println(e.Name)     <span class="hljs-comment">// Output: Bob</span>
fmt.Println(e.Position) <span class="hljs-comment">// Output: Developer</span>
</code></pre>
<p>In the code above, the <code>Employee</code> struct embeds the <code>Person</code> struct, and the fields of <code>Person</code> can be accessed directly like <code>e.Name</code>. This mimics some of the behavior you’d expect from inheritance in other languages, but it’s done through composition.</p>
<p>While Go lacks inheritance, it achieves polymorphism through <strong>interfaces</strong>. An <strong>interface</strong> is a type that specifies a set of method signatures. A type is said to implement an interface if it provides the methods declared by that interface.</p>
<p>What makes Go unique is that it uses <strong>implicit implementation</strong>, meaning that a type does not need to explicitly declare that it implements an interface – it just has to match the method signatures.</p>
<p>Let’s see an example:</p>
<pre><code class="lang-go"><span class="hljs-keyword">type</span> Speaker <span class="hljs-keyword">interface</span> {
    Speak() <span class="hljs-keyword">string</span>
}

<span class="hljs-keyword">type</span> Person <span class="hljs-keyword">struct</span> {
    Name <span class="hljs-keyword">string</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(p Person)</span> <span class="hljs-title">Speak</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> {
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Hi, my name is "</span> + p.Name
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">saySomething</span><span class="hljs-params">(s Speaker)</span></span> {
    fmt.Println(s.Speak())
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    p := Person{Name: <span class="hljs-string">"Alice"</span>}
    saySomething(p)  <span class="hljs-comment">// Output: Hi, my name is Alice</span>
}
</code></pre>
<p>In this example, <code>Person</code> implements the <code>Speaker</code> interface by defining a <code>Speak</code> method. The function <code>saySomething</code> takes any type that implements the <code>Speaker</code> interface, demonstrating <strong>polymorphism</strong>. Go’s interfaces provide a flexible way to design code that is <strong>clean and extensible</strong> without needing to rely on traditional inheritance.</p>
<h2 id="heading-go-standard-library">Go Standard Library</h2>
<p>It’s important to become familiar with Go's standard library. It contains a comprehensive collection of packaged libraries that provide you with a wide range of functionalities for tasks like file handling, network communication, string manipulation, data structures, cryptography, testing, and more. This allows you to perform common programming tasks without the need to install external packages.</p>
<h3 id="heading-accessing-and-using-a-package-from-the-standard-library">Accessing and Using a Package from the Standard Library</h3>
<p>To access a package from the standard library, you simply import it into your Go file using the <code>import</code> statement. Then, you can use the package's functions directly.</p>
<p>Some of the packages you can import from the standard library include:</p>
<ul>
<li><p><code>fmt</code> for formatted I/O</p>
</li>
<li><p><code>net/http</code> for building web servers</p>
</li>
<li><p><code>io</code> for I/O operations</p>
</li>
<li><p><code>strings</code> for string manipulation</p>
</li>
<li><p><code>time</code> for date and time operations</p>
</li>
</ul>
<p>For example, let’s look at the <code>fmt</code> package, which is used for formatted input and output. Here's a basic example of how to use the <code>fmt</code> package to print formatted output:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    name := <span class="hljs-string">"Alice"</span>
    age := <span class="hljs-number">30</span>
    fmt.Printf(<span class="hljs-string">"Hello, my name is %s and I am %d years old.\n"</span>, name, age)
}
</code></pre>
<p>In this example:</p>
<ul>
<li><p>The <code>import "fmt"</code> line allows us to access the <code>fmt</code> package from the standard library.</p>
</li>
<li><p>We use <code>fmt.Printf</code> to format and print a string that includes a name (<code>%s</code> for strings) and an age (<code>%d</code> for integers).</p>
</li>
</ul>
<p>Each package in the standard library is well-documented, with plenty of examples, so it’s a good idea to explore the official Go documentation to better understand how to use these packages in your projects. You can find the documentation for the Go standard library <a target="_blank" href="https://pkg.go.dev/std">here</a>.</p>
<h2 id="heading-testing-in-go">Testing in Go</h2>
<p>Testing is a first-class citizen in Go. This means that Go treats testing as a core, integral part of the development process.</p>
<p>Go’s testing framework is built around the <code>testing</code> package, which provides the tools necessary to write tests. You write your tests in separate files, which are automatically detected and executed by the Go tool.</p>
<p>To write a test, you need to add the suffix <code>_test.go</code>. For example, if your main code file is <code>math</code>, the tests for that file would go into <code>math_test.go</code>.</p>
<p>Let’s see how to write a simple test. Let’s say we have a simple function in <code>math.go</code>:</p>
<pre><code class="lang-go">
<span class="hljs-keyword">package</span> math

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Add</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> {
    <span class="hljs-keyword">return</span> a + b
}
</code></pre>
<p>To test the <code>Add</code> function, you need to create a test file called <code>math_test.go</code>:</p>
<pre><code class="lang-go">
<span class="hljs-keyword">package</span> math

<span class="hljs-keyword">import</span> <span class="hljs-string">"testing"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestAdd</span><span class="hljs-params">(t *testing.T)</span></span> {
    result := Add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>)
    expected := <span class="hljs-number">5</span>
    <span class="hljs-keyword">if</span> result != expected {
        t.Errorf(<span class="hljs-string">"Add(2, 3) = %d; want %d"</span>, result, expected)
    }
}
</code></pre>
<p>In the test above:</p>
<ul>
<li><p>The <code>TestAdd</code> function is defined to test the <code>Add</code> function.</p>
</li>
<li><p>The <code>t.Errorf</code> is used to report an error if the result doesn't match the expected value.</p>
</li>
</ul>
<p>To run the test, you use this command in your terminal:</p>
<pre><code class="lang-bash">go <span class="hljs-built_in">test</span>
</code></pre>
<p>You can also get more verbose output by adding the <code>-v</code> flag like so:</p>
<pre><code class="lang-bash">go <span class="hljs-built_in">test</span> -v
</code></pre>
<p>This is just the basics, as there are other types of tests, such as table-driven tests and benchmarking.</p>
<h2 id="heading-thats-a-wrap">That’s a Wrap!</h2>
<p>In this article, we took a look at nine key concepts to learn as a beginner getting started with Golang.</p>
<p>And keep in mind that this isn’t everything you’ll need to know when you’re learning Go – these are just what I consider to be the most important basics. And they should help you get your foot in the door of the world of Go.</p>
<p>If you think I missed a key concept, I’d love it if you’d share it with me so I can update the article. Thank you!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Understand How Express.js Works by Building Your Own Server Multiplexer from Scratch ]]>
                </title>
                <description>
                    <![CDATA[ Kata Machines have become the go-to method for mastering tough concepts, and it's hard to find a better tool for deliberate practice. If you haven’t come across a kata yet, trust me—you will soon enough. There’s a reason why developers love katas, wh... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/understand-how-expressjs-works-by-building-your-own-server-multiplexer-from-scratch/</link>
                <guid isPermaLink="false">66feb8e20772faf5564db923</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webdev ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Express ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sifundo ]]>
                </dc:creator>
                <pubDate>Thu, 03 Oct 2024 15:31:46 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/urBiLDuUhMU/upload/65f541a7f0d11691008b4e93d89f2d29.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Kata Machines have become the go-to method for mastering tough concepts, and it's hard to find a better tool for deliberate practice.</p>
<p>If you haven’t come across a kata yet, trust me—you will soon enough.</p>
<p>There’s a reason why developers love katas, whether they use them to sharpen their skills for personal projects or prepare for interviews.</p>
<p>A kata is all about <strong>deliberate</strong> practice. It comes from martial arts like Karate and Judo, and, according to Wikipedia, it’s defined as a pre-determined sequence of movements, techniques, and patterns that follow a specific order (source: <a target="_blank" href="https://en.wikipedia.org/wiki/Kata">wikipedia</a>).</p>
<p>Kata Machines come from this idea: learning through drills and deliberate, conscious (choreographed) practice.</p>
<p>I realized just how perfect katas are when I was learning Haskell back in the day. If you know, you know. Haskell was a beast to learn for me back then!</p>
<p>So, I thought, why not do the same for the backend? Just pick one high-level concept, and drill down on it repeatedly and deliberately to its core and first principles.</p>
<p>In this article, I picked server-side frameworks. We're going to pick apart the idea of a "framework" using Express as an example.</p>
<p>We’re going to take high-level Express:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);

<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">3000</span>;
<span class="hljs-keyword">const</span> app = express();

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send(<span class="hljs-string">"Hello, world!"</span>);
});

app.listen(PORT, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Server listening on port:"</span>, PORT));
</code></pre>
<p>And drill all the way down, repeatedly, until we touch Node.js native code:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TCPWrap::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&lt;Value&gt;&amp; args)</span> </span>{
  CHECK(args.IsConstructCall());
  CHECK(args[<span class="hljs-number">0</span>]-&gt;IsInt32());
  Environment* env = Environment::GetCurrent(args);
  <span class="hljs-keyword">int</span> type_value = args[<span class="hljs-number">0</span>].As&lt;Int32&gt;()-&gt;Value();
  TCPWrap::SocketType type = <span class="hljs-keyword">static_cast</span>&lt;TCPWrap::SocketType&gt;(type_value);
  ProviderType provider;
  <span class="hljs-keyword">switch</span> (type) {
    <span class="hljs-keyword">case</span> SOCKET:
      provider = PROVIDER_TCPWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> SERVER:
      provider = PROVIDER_TCPSERVERWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
      UNREACHABLE();
  }
  <span class="hljs-keyword">new</span> TCPWrap(env, args.This(), provider);
}
</code></pre>
<p>And having gained this new intuition, we’ll build back up with a custom "Express" implementation:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-comment">// To be implemented</span>
  }
  <span class="hljs-keyword">return</span> {
    hook
  };
}

<span class="hljs-keyword">const</span> app = serverMux();

<span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  app.hook(req, res);
});
</code></pre>
<p>It’s going to be quite the journey – and a rewarding one at that!</p>
<p>I'm assuming you have some backend knowledge and classify yourself as an advanced beginner who’s looking to level up.</p>
<p>If that sounds like you, we’re ready to proceed.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#form-1--server-side-frameworks">Form 1: Server-Side Frameworks</a></p>
<ul>
<li><p><a class="post-section-overview" href="#first-drill--unpacking-expressjs">First Drill: Unpacking Express.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-server">The Server</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-socket-in-nodejs">The Socket in Node.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-socket-in-nodejs-source-code">The Socket in Node.js Source Code</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#form-2--implementing-a-custom-server-mux">Form 2: Implementing a Custom Server Mux</a></p>
<ul>
<li><p><a class="post-section-overview" href="#creating-our-custom-router">Creating Our Custom Router</a></p>
</li>
<li><p><a class="post-section-overview" href="#basic-mux-skeleton">Basic Mux Skeleton</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-hook-function">The Hook Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#why-use-a-queue-">Why Use a Queue?</a></p>
<ul>
<li><a class="post-section-overview" href="#queue-operations">Queue Operations</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#request-wrapper">Request Wrapper</a></p>
</li>
<li><p><a class="post-section-overview" href="#testing-the-queue">Testing the Queue</a></p>
</li>
<li><p><a class="post-section-overview" href="#processing-requests">Processing Requests</a></p>
</li>
<li><p><a class="post-section-overview" href="#lookup-table-and-handlers">Lookup Table and Handlers</a></p>
</li>
<li><p><a class="post-section-overview" href="#registering-handlers">Registering Handlers</a></p>
</li>
</ul>
</li>
</ul>
<ul>
<li><a class="post-section-overview" href="#wrapping-up">Wrapping Up</a></li>
</ul>
<h2 id="heading-form-1-server-side-frameworks">Form 1: Server-Side Frameworks</h2>
<p>The term "server-side framework" is broad. Think about it: <code>mysql2</code> could be considered a framework depending on how you classify frameworks and libraries. Even <code>sharp.js</code> for image editing could fit under the umbrella of server-side frameworks, right?</p>
<p>But the question is, what type of framework is Express.js?</p>
<p>Express is a multiplexer—specifically, a server multiplexer (server mux). I promise, the term isn’t as complex as it sounds. The implementation, though—that’s a whole different story.</p>
<p>In simple terms, a server mux is a router. Of course, Express and other server muxes handle more than just routing, but that’s the core idea.</p>
<p>Express takes in <code>request</code> and <code>response</code> objects from the server and routes them. Don’t worry, we’ll dive into routing soon.</p>
<p>Here’s an interesting point: if Express isn’t the server, then what exactly is the server?</p>
<p>To answer that, we need to look at the Express.js source code, which you can clone from GitHub:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/expressjs/express.git
</code></pre>
<p>Once you’re set, we can dive right in with our first deep dive.</p>
<h3 id="heading-first-drill-unpacking-expressjs">First Drill: Unpacking Express.js</h3>
<p>Open your Express source code in an editor. You’ll find the entry file <code>express.js</code> in the <code>lib</code> folder.</p>
<p>You can skim the file, but we’re going to focus on lines 42 and 43—the heart of it all:</p>
<pre><code class="lang-js">mixin(app, EventEmitter.prototype, <span class="hljs-literal">false</span>);
mixin(app, proto, <span class="hljs-literal">false</span>);
</code></pre>
<p>What you’re looking at is object composition: a design pattern where an object is created by combining the properties and methods of other objects.</p>
<p>Our target object here is <code>proto</code>, which is imported from <code>application.js</code>, the core of Express.</p>
<p>Let’s open that file. There’s a lot of code, but remember, our goal is to figure out where the server is within Express.</p>
<p>If there’s one function in Express that everyone likely knows, it’s <code>listen</code>. The essence of a server is to "listen" over a network. So, do a quick <code>Ctrl+F</code> for "listen," and you’ll find the definition on line 633:</p>
<pre><code class="lang-js">app.listen = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">listen</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> server = http.createServer(<span class="hljs-built_in">this</span>);
  <span class="hljs-keyword">return</span> server.listen.apply(server, <span class="hljs-built_in">arguments</span>);
};
</code></pre>
<p>There it is, the famous <code>listen</code> function. Did we just find the server?</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> server = http.createServer(<span class="hljs-built_in">this</span>);
</code></pre>
<p>We’ve already seen a version of this in the intro:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  app.hook(req, res);
});
</code></pre>
<p>This confirms that Express is indeed a server mux, and the actual server is returned by the Node.js <code>createServer</code> function from the <code>http</code> package.</p>
<p>That’s some solid progress!</p>
<p>We’ve peeled back a layer, but we can go deeper. What exactly does <code>createServer</code> do, and what is this <code>server</code> object?</p>
<h3 id="heading-the-server">The Server</h3>
<p>A server is the basic unit of the backend. At its core, the concept is simple: how can two or more processes communicate over a network?</p>
<p>This is the fundamental idea behind network programming. We have devices equipped with IP addresses for identification and ports for data exchange over a network.</p>
<p>The communication itself is complex, which is where protocols come in to facilitate the process.</p>
<p>The most common protocols are UDP and TCP:</p>
<ul>
<li><p><strong>UDP</strong> is a connectionless protocol and does not guarantee reliable communication, but allows for low-latency and efficient data transfer. This is ideal for time-sensitive applications such as video conferencing, online gaming, and voice over IP (VoIP) (source <a target="_blank" href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">Wikipedia</a>).</p>
</li>
<li><p><strong>TCP</strong> is a connection-oriented protocol with reliable, ordered, and error-checked data transmission between applications on networked devices. It’s a major part of internet applications (source <a target="_blank" href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">Wikipedia</a>).</p>
</li>
</ul>
<p>TCP is the most widely used protocol due to its reliability, and most server-side applications you’ll work with, including Express, are TCP-based.</p>
<p>Although I love the quirks and power of UDP, we’ll focus on TCP, tracing its roots in Node.js.</p>
<p>We’ve already seen a glimpse of this:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TCPWrap::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&lt;Value&gt;&amp; args)</span> </span>{
  <span class="hljs-comment">// some code</span>
  <span class="hljs-keyword">new</span> TCPWrap(env, args.This(), provider);
}
</code></pre>
<p>Before we dig into that, we need to answer a key question: What does it really mean to be a server process?</p>
<p>Without getting too deep into file descriptors, sockets, or network layers, a server is an OS-level object responsible for handling communication between nodes. When you call:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">"node:http"</span>);

<span class="hljs-keyword">const</span> something = http.createServer({});
</code></pre>
<p>You’re creating an OS-level object, commonly known as a <strong>socket</strong>. This socket facilitates network communication between devices, along with handling data encoding and decoding.</p>
<p>In short, <code>createServer</code> abstracts and returns this socket object.</p>
<p>And, yes, we can implement this socket in Node.js. Remember, Node.js has native access to the OS, allowing JavaScript to function at the system level.</p>
<h3 id="heading-the-socket-in-nodejs">The Socket in Node.js</h3>
<p>Here’s some code that creates a server socket:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Using Node v20</span>
<span class="hljs-keyword">const</span> net = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:net'</span>);

<span class="hljs-keyword">const</span> server = net.createServer(<span class="hljs-function">(<span class="hljs-params">c</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'client connected'</span>, c.remoteAddress);
  c.write(<span class="hljs-string">"Hello; world"</span>);

  c.on(<span class="hljs-string">'end'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'client disconnected'</span>);
  });
});

server.on(<span class="hljs-string">'error'</span>, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
  <span class="hljs-keyword">throw</span> err;
});

server.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'server bound'</span>);
});
</code></pre>
<p>While <code>net.createServer((c)</code> is still a high-level abstraction like <code>http.createServer</code>, it returns the raw socket.</p>
<p>The <code>c</code> object represents the client that made the connection (dial). Beyond writing to it, we can do much more.</p>
<p>For instance, here’s a simple write operation:</p>
<pre><code class="lang-js">c.write(<span class="hljs-string">"Hello world"</span>);
</code></pre>
<p>Our socket is running on <code>localhost:3000</code>. If you make a request (or use <code>curl</code>):</p>
<pre><code class="lang-bash">curl localhost:3000
</code></pre>
<p>The OS-level network stack encodes not only your data but also information about who you are and where to find you—in the form of a response, among other things.</p>
<p>This is what the server receives, and it’s important to know where to send the response (like IP, and so on).</p>
<p>So, the <code>c</code> object represents all of that!</p>
<p>We’ve covered a lot of the surface-level concepts, but before we wrap up this part, here’s a bonus challenge:</p>
<p>Try writing a class on the server to manage multiple connections. You could store these connections in a data structure and periodically send data to them while the connection remains open.</p>
<p>We’re about three layers deep now, but the journey isn’t over. Remember the goal?</p>
<p>Now it’s time to clone the Node.js source code. Don’t worry, we’ll only focus on the relevant parts.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/nodejs/node.git
</code></pre>
<h3 id="heading-the-socket-in-nodejs-source-code">The Socket in Node.js Source Code</h3>
<p>Let the tracing begin! Node.js is a massive codebase – it’s an entire engine that does way more than just handle sockets. But we only care about the networking part today.</p>
<p>First, navigate to the <code>lib</code> folder, and inside you’ll find a file called <code>net.js</code>. This is where most of the work happens for network applications. If you scroll down to line 210, you’ll see a familiar sight:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createServer</span>(<span class="hljs-params">options, connectionListener</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Server(options, connectionListener);
}
</code></pre>
<p>That’s it! Every time we create a server, it calls this function and returns a <code>Server</code> object. Anytime you see <code>new</code> in JavaScript, you should have a lightbulb moment—it means a new object or class (blueprint) is being created.</p>
<p>So we can trace and find the <code>Server</code> definition:</p>
<p>On line 1737</p>
<p>At first glance, it might seem like nothing special is happening. But JavaScript has a sneaky way of hiding complexity.</p>
<p>Here’s the thing: JavaScript is a prototype-based language. This means that objects can inherit features from other objects through prototypes. On line 1791, we see this in action:</p>
<pre><code class="lang-js">ObjectSetPrototypeOf(Server.prototype, EventEmitter.prototype);
</code></pre>
<p>In plain English: our <code>Server</code> object is inheriting all the behavior from other objects like <code>EventEmitter</code>, for example. This is a common pattern in JavaScript libraries – remember the mixin in Express?</p>
<p>At this point, if you’ve never worked with prototypes or Object-Oriented JavaScript (OOJS), this might feel like advanced territory. But don’t worry – the good folks at <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">MDN</a> have an excellent guide on prototypes to get you up to speed.</p>
<p>Now, what’s one thing we know for sure about a Node.js server? It has a <code>listen</code> function. We use it all the time in server-side code (even in frameworks like Express). So, let’s check if our <code>Server</code> object has a <code>listen</code> function.</p>
<p>Scroll down a bit more, and there it is on line 2006:</p>
<pre><code class="lang-js">Server.prototype.listen = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">...args</span>) </span>{}
</code></pre>
<p>This function handles a lot of stuff—like validating the port number—but the key part starts around line 2016, where the comment clearly tells us:</p>
<pre><code class="lang-js"><span class="hljs-comment">// start TCP server listening on host:port</span>
</code></pre>
<p>We know what TCP is!</p>
<p>The important functions here are <code>lookupAndListen</code> and <code>listenInCluster</code>. They are responsible for starting the actual TCP server:</p>
<pre><code class="lang-js"><span class="hljs-comment">// start TCP server listening on host:port</span>
<span class="hljs-keyword">if</span> (options.host) {
  lookupAndListen(<span class="hljs-built_in">this</span>, options.port | <span class="hljs-number">0</span>, options.host, backlog, options.exclusive, flags);
} <span class="hljs-keyword">else</span> {
  listenInCluster(<span class="hljs-built_in">this</span>, <span class="hljs-literal">null</span>, options.port | <span class="hljs-number">0</span>, <span class="hljs-number">4</span>, backlog, <span class="hljs-literal">undefined</span>, options.exclusive);
}
</code></pre>
<p>Digging into <code>lookupAndListen</code> (line 2156), we find that it calls <code>listenInCluster</code>, which leads us to another function: <code>server._listen2</code> (yep, more tracing!):</p>
<pre><code class="lang-js">server._listen2(address, port, addressType, backlog, fd, flags);
</code></pre>
<p>As the comments explain, this is all about backward compatibility:</p>
<pre><code class="lang-js"><span class="hljs-comment">// _listen2 sets up the listened handle, it is still named like this</span>
<span class="hljs-comment">// to avoid breaking code that wraps this method</span>
</code></pre>
<p>I know this might feel like a wild goose chase, but trust me, tracing through a large codebase like Node.js requires patience. We’re getting close.</p>
<p>So, <code>._listen2</code> is defined in our <code>Server</code> object’s prototype and points to a function called <code>setupListenHandle</code> (line 1856). This function is the real hub where everything comes together.</p>
<p>Around line 1870 and 1883, you’ll find the function <code>createServerHandle</code>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createServerHandle</span>(<span class="hljs-params">address, port, addressType, fd, flags</span>) </span>{
   handle = <span class="hljs-keyword">new</span> TCP(TCPConstants.SERVER);
   isTCP = <span class="hljs-literal">true</span>;
   <span class="hljs-keyword">return</span> handle;
}
</code></pre>
<p>Finally! We’ve hit the core: the <code>TCP</code> object. This is where the actual TCP server is created, the core. We could stop here, satisfied that we’ve found the TCP server, but why not dig deeper?</p>
<p>Remember that <code>new TCP</code> is creating an object, so we need to figure out what <code>TCP</code> actually represents.</p>
<p>Go back up to line 68, where you’ll see the following import:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> {
  TCP,
  TCPConnectWrap,
  <span class="hljs-attr">constants</span>: TCPConstants,
} = internalBinding(<span class="hljs-string">'tcp_wrap'</span>);
</code></pre>
<p>This is where things get interesting. You might wonder: “What kind of import is that? It’s not your regular <code>require</code> or <code>import</code> statement.” That’s because JavaScript alone can’t handle TCP servers—it needs help from C++.</p>
<p>Node.js, which is built on the V8 engine, relies on C++ bindings to do the heavy lifting. These bindings are like a bridge, allowing JavaScript to communicate with low-level system functions (like creating a TCP server). <code>internalBinding('tcp_wrap')</code> is one of these bridges.</p>
<p>To truly trace things to their source, we need to dive into the Node.js C++ code. You’ll find <code>tcp_wrap.cc</code> in the <code>src</code> folder (among others like <code>crypto</code>, <code>streams</code>, <code>async</code>, <code>fs</code>). Open it, and you’ll find this function:</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TCPWrap::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&lt;Value&gt;&amp; args)</span> </span>{
  CHECK(args.IsConstructCall());
  CHECK(args[<span class="hljs-number">0</span>]-&gt;IsInt32());
  Environment* env = Environment::GetCurrent(args);
  <span class="hljs-keyword">int</span> type_value = args[<span class="hljs-number">0</span>].As&lt;Int32&gt;()-&gt;Value();
  TCPWrap::SocketType type = <span class="hljs-keyword">static_cast</span>&lt;TCPWrap::SocketType&gt;(type_value);
  ProviderType provider;
  <span class="hljs-keyword">switch</span> (type) {
    <span class="hljs-keyword">case</span> SOCKET:
      provider = PROVIDER_TCPWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> SERVER:
      provider = PROVIDER_TCPSERVERWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
      UNREACHABLE();
  }
  <span class="hljs-keyword">new</span> TCPWrap(env, args.This(), provider);
}
</code></pre>
<p>This is where the TCP server is <em>actually</em> created. You can see more familiar functions like <code>bind</code>, and everything JavaScript does is just a mirror of these lower-level operations.</p>
<p>We’ve traced our way from high-level JavaScript all the way down to C++—the true beginning of a TCP server in Node.js.</p>
<p>We've completed the first part of the introduction: "And drill all the way down repeatedly until we touch Node.js native code" and now it's time to build up.</p>
<h2 id="heading-form-2-implementing-a-custom-server-mux">Form 2: Implementing a Custom Server Mux</h2>
<p>Before diving into the code, the goal isn’t to focus on the complexity of mux (multiplexer) development (because that can get complicated). Instead, it’s to show how the <strong>server</strong> and <strong>mux</strong> fit together.</p>
<p>If anything, this is the key takeaway: the flow from the server to the router, and ultimately to the caller (the client that made the request).</p>
<p>Remember, we've already seen a similar concept in Express:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Express app inherits from Node's EventEmitter</span>
mixin(app, EventEmitter.prototype, <span class="hljs-literal">false</span>);
<span class="hljs-comment">// Implements the server mux with functions like listen, handle, middleware</span>
mixin(app, proto, <span class="hljs-literal">false</span>);
</code></pre>
<p>Behind the scenes, a lot of complex code is abstracted away. This helps simplify things and makes the code cleaner, but for teaching purposes, we’ll take a more verbose approach. This way, you can see how everything connects.</p>
<h3 id="heading-creating-our-custom-router">Creating Our Custom Router</h3>
<p>Let's start simple and build a basic server. You probably already know how to create a native server in Node.js:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
   app.hook(req, res);
});
</code></pre>
<p>Here, we’re introducing an object <code>app</code> with a <code>hook</code> function (which we’ll implement shortly). This is where the server redirects the <code>req</code> and <code>res</code> to our custom router. This <strong>hook</strong> is the meeting point—the interaction between the server and the router (mux).</p>
<h3 id="heading-basic-mux-skeleton">Basic Mux Skeleton</h3>
<p>Let's start by creating the structure of our mux:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-comment">// To be implemented</span>
  }
  <span class="hljs-keyword">return</span> {
    hook
  };
}

<span class="hljs-keyword">const</span> app = serverMux();

<span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  app.hook(req, res);
});
</code></pre>
<h3 id="heading-the-hook-function">The Hook Function</h3>
<p>The <code>hook</code> function is our middleman between the server and the mux. It receives the request (<code>req</code>) and response (<code>res</code>) objects from the server and passes them to our mux:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    requestsQueue.push(requestWrapper(req, res));
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"new request!"</span>);
    processRequests();
}
</code></pre>
<p>Here, we introduced a few new things:</p>
<ul>
<li><p><code>requestWrapper</code>: A function to wrap the <code>req</code> and <code>res</code>.</p>
</li>
<li><p><code>processRequests</code>: A function to handle the request processing.</p>
</li>
<li><p><code>requestsQueue</code>: A basic JavaScript array that will act as our queue for handling requests.</p>
</li>
</ul>
<p>Let's update <code>serverMux</code> to reflect this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> requestsQueue = [];

    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processRequests</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-comment">// To be implemented</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
      requestsQueue.push(requestWrapper(req, res));
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"new request!"</span>);
      processRequests();
    }

    <span class="hljs-keyword">return</span> {
      hook
    };
}
</code></pre>
<h3 id="heading-why-use-a-queue">Why Use a Queue?</h3>
<p>You might be wondering why we’re using a queue instead of handling requests immediately like Express does with <code>app.handle</code>. Well, storing requests in a queue helps simulate an event loop. This will give us better visibility into how requests are processed, one at a time.</p>
<h4 id="heading-queue-operations">Queue Operations</h4>
<p>A queue is a first-in, first-out (FIFO) data structure. Just like a line at the store, the request that arrives first gets processed first.</p>
<p>In our case, the <code>requestsQueue</code> is an array. Here’s how we’ll handle enqueueing and dequeueing:</p>
<ul>
<li><p><strong>Enqueue (push)</strong>: We push requests into the queue with <code>requestsQueue.push(requestWrapper(req, res));</code></p>
</li>
<li><p><strong>Dequeue (shift)</strong>: We pull the next request out of the queue with <code>const c = requestsQueue.shift();</code></p>
</li>
</ul>
<h3 id="heading-request-wrapper">Request Wrapper</h3>
<p>The <code>requestWrapper</code> function is a simple utility that wraps the incoming <code>req</code> and <code>res</code> objects, and extracts some useful information:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">requestWrapper</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">url</span>: req.url,
      <span class="hljs-attr">method</span>: req.method,
      req,
      res
    };
}
</code></pre>
<p>In more advanced frameworks like <a target="_blank" href="https://hono.dev/">Hono.js</a>, the request wrapper might add additional functionality, such as helper methods for setting headers or parsing body content. For now, we’re keeping things simple and just returning the request and response with the URL and method.</p>
<h3 id="heading-testing-the-queue">Testing the Queue</h3>
<p>Let’s test this out by logging the request queue on every new request. Update your <code>hook</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    requestsQueue.push(requestWrapper(req, res));
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"New request queued!"</span>, requestsQueue);
    processRequests();
}
</code></pre>
<p>Start the server with:</p>
<pre><code class="lang-bash">node index.js
</code></pre>
<p>Now, open another terminal and make a request to the server:</p>
<pre><code class="lang-bash">curl http://localhost:3000
</code></pre>
<p>You should see the queue logged in the console. The terminal might look like it's hanging because we haven’t responded to the request yet. You can exit the process manually for now.</p>
<h3 id="heading-processing-requests">Processing Requests</h3>
<p>Here’s the full <code>processRequests</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processRequests</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">while</span> (requestsQueue.length &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">const</span> c = requestsQueue.shift();
        <span class="hljs-keyword">if</span> (c) {
            <span class="hljs-keyword">const</span> handler = lookupTable[c.url] || lookupTable[<span class="hljs-string">"/notfound"</span>];
            <span class="hljs-keyword">if</span> (handler) {
                (<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
                    handler(c.req, c.res);
                })();
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Missing not found handler!"</span>);
            }
        }
    }
}
</code></pre>
<p>Let’s break it down:</p>
<ol>
<li><p><strong>Queue processing</strong>: We loop through the queue, dequeueing each request one by one.</p>
</li>
<li><p><strong>Handler lookup</strong>: For each request, we check if a handler exists in the <code>lookupTable</code> for the URL. If it doesn’t, we fall back to a <code>/notfound</code> handler.</p>
</li>
<li><p><strong>Handler execution</strong>: We execute the handler, passing the request and response objects.</p>
</li>
</ol>
<h3 id="heading-lookup-table-and-handlers">Lookup Table and Handlers</h3>
<p>We need a way to map URLs to their respective handlers. This is where the <code>lookupTable</code> comes in:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> lookupTable = {
    <span class="hljs-string">"/"</span>: <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
      res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
      res.end(<span class="hljs-string">'Hello, World!\n'</span>);
    },
    <span class="hljs-string">"/notfound"</span>: <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
      res.writeHead(<span class="hljs-number">404</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
      res.end(<span class="hljs-string">'404 Not Found\n'</span>);
    }
};
</code></pre>
<p>When a request comes in, we check if the URL matches an entry in the table. If it does, we call the corresponding handler function.</p>
<p>For example, calling <code>curl http://localhost:3000</code> will hit the <code>/</code> route and return "Hello, World!". If you hit a non-existent route like <code>/random</code>, it will trigger the 404 handler.</p>
<h3 id="heading-registering-handlers">Registering Handlers</h3>
<p>Finally, let’s add a method to register new handlers dynamically:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> lookupTable = {};

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">registerHandler</span>(<span class="hljs-params">path, handler</span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path !== <span class="hljs-string">'string'</span> || !path) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Path must be a non-empty string"</span>);
    }
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> handler !== <span class="hljs-string">'function'</span>) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Handler must be a function"</span>);
    }
    lookupTable[path] = handler;
  }

  <span class="hljs-keyword">return</span> {
    hook,
    registerHandler
  };
}
</code></pre>
<p>Now, we can dynamically register new routes with their handlers:</p>
<pre><code class="lang-js">app.registerHandler(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
    res.end(<span class="hljs-string">'Home Page\n'</span>);
});

app.registerHandler(<span class="hljs-string">"/about"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
    res.end(<span class="hljs-string">'About Us\n'</span>);
});
</code></pre>
<p>Here's a full example of <code>registerHandler</code> in action:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> app =  serverMux()


app.registerHandler(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

  res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });

  res.end(<span class="hljs-string">'Hello, World!'</span>);



})

app.registerHandler(<span class="hljs-string">"/about"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

    res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/html'</span> });

    res.end(<span class="hljs-string">'&lt;h1&gt;About Us&lt;/h1&gt;'</span>);

})


app.registerHandler(<span class="hljs-string">"/contact"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

  res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/html'</span> });

  res.end(<span class="hljs-string">'&lt;h1&gt;Contact Us&lt;/h1&gt;'</span>);

})


app.registerHandler(<span class="hljs-string">"/api/data"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

  res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> });

  res.end(<span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Some data from the API'</span> }));

})


app.registerHandler(<span class="hljs-string">"/notfound"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

   res.writeHead(<span class="hljs-number">404</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });

    res.end(<span class="hljs-string">'404 Not Found'</span>);

})



<span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {

   <span class="hljs-built_in">console</span>.log(req.url)

   app.hook(req, res)

});
</code></pre>
<p>Notice how similar it is to Express?</p>
<pre><code class="lang-js">app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

})
</code></pre>
<p>Just a bit more verbose!</p>
<p>Now, run the server and put it to the test by pasting this into your terminal:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">for</span> /l %i <span class="hljs-keyword">in</span> (1,1,100) <span class="hljs-keyword">do</span> curl -X GET http://localhost:3000
</code></pre>
<p>This will send 100 requests. Try opening two or more terminals and running the same command concurrently to see how your server handles the load.</p>
<p>Congratulations! You’ve built a basic server multiplexer (mux). It may not revolutionize the world, but it's a solid starting point to understand how routing works in web frameworks.</p>
<h1 id="heading-wrapping-up">Wrapping Up</h1>
<p>In this article, we took a deep dive into the concept of server-side frameworks, using Express as our primary example. We traced it from its high-level abstractions all the way down to the native TCP server built in C++. Then, to cement these ideas, we built our own simple server mux.</p>
<p>It’s a powerful learning exercise, because we stripped away the magic and dug into the core of how things work. While this example is just the tip of the iceberg, it gives you the tools to explore even deeper. For a challenge, look into how Express handles pattern matching and registering routes—try improving our simple mux!</p>
<p>I left out more advanced topics like updating our queue with a linked list and simulating concurrent requests, so this is something you can explore.</p>
<p>Thanks for reading! I hope you enjoyed this exploration as much as I did writing it. If you have any thoughts, questions, or just want to connect I am on <a target="_blank" href="https://x.com/codelit09">x</a>, feel free to reach out.</p>
<p>And of course, enjoy your timezone!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Skills You Need to Become a Backend Developer – A Roadmap for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ In this guide, I'll discuss the basic skills you need and steps you can take to become a backend developer. I'll give you a simple roadmap that'll help you know where you are and where you should go next. Front End vs Back End Every website has two p... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/skills-you-need-to-become-a-backend-developer-roadmap/</link>
                <guid isPermaLink="false">66d71f6c2567a1ecb3ff38c6</guid>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Programming with Shahan ]]>
                </dc:creator>
                <pubDate>Tue, 03 Sep 2024 14:38:36 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1725110852270/9185d74e-4b0f-482f-8cc2-abbfc70a5849.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this guide, I'll discuss the basic skills you need and steps you can take to become a backend developer.</p>
<p>I'll give you a simple roadmap that'll help you know where you are and where you should go next.</p>
<h2 id="heading-front-end-vs-back-end">Front End vs Back End</h2>
<p>Every website has two parts: a <strong>front end</strong> and a <strong>back end</strong>.</p>
<p>The front end is the part that you see in the browser and interact with. Basically, it represents all the visual aspects of a website.</p>
<p>The back end is the part that powers the front end. It's <em>behind the scenes</em>, and it's mainly concerned with storing and accessing data using databases, APIs, and so on.</p>
<p>Because of this, web development jobs fall into three main categories:</p>
<ul>
<li><p>👨‍💻 Front-end development</p>
</li>
<li><p>🛟 Back-end development</p>
</li>
<li><p>🚢 Full-stack development (involves both front-end and back-end development)</p>
</li>
</ul>
<h2 id="heading-what-exactly-does-a-backend-developer-do">👷‍♂️What Exactly Does a Backend Developer Do?</h2>
<p>Backend developers are responsible for constructing the foundational systems that drive the functionality of applications that users engage with.</p>
<p>This includes various tasks such as designing the architecture, and then implementing and maintaining these critical systems.</p>
<p>Their responsibilities typically involve working with:</p>
<ul>
<li><p>💾 Databases, such as MySQL,</p>
</li>
<li><p>✂️ Frameworks, like Laravel or Ruby on Rails, and</p>
</li>
<li><p>🧨 APIs (Application Programming Interfaces).</p>
</li>
</ul>
<p>Backend devs ensure that the backend infrastructure operates seamlessly, enabling smooth interactions between the user interface and the underlying data and processes.</p>
<p>Here are some of the core responsibilities of a backend developer:</p>
<ul>
<li><p>Understanding the website's performance needs and goals</p>
</li>
<li><p>Developing and managing APIs for the website</p>
</li>
<li><p>Developing systems for secure data storage and processing (especially special use cases like payments)</p>
</li>
<li><p>Writing code, testing it, maintaining it, and developing solutions to bugs</p>
</li>
<li><p>Designing the site's architecture using established methodologies like Agile/Scrum and various frameworks</p>
</li>
<li><p>Organizing the system logic effectively</p>
</li>
<li><p>Providing solutions to address system-related issues and challenges</p>
</li>
</ul>
<h2 id="heading-what-you-need-to-know-to-become-a-backend-developer">🥷 What You Need to Know to Become a Backend Developer</h2>
<p>Becoming a proficient backend developer requires mastering various skills and technologies.</p>
<p>Below, I've outline a comprehensive roadmap to help you achieve this goal as quickly as possible.</p>
<p>Just keep in mind that everyone learns at a different pace, so it's hard to set a specific timeframe on how long this will take. Some might be able to get through it in six months or less, but others might take significantly more time.</p>
<h3 id="heading-step-1-foundations-of-backend-development"><strong>Step 1: Foundations of Backend Development 🏗️</strong></h3>
<ul>
<li><p>Understand the role and responsibilities of a back-end developer. Familiarize yourself with databases, frameworks, and APIs.</p>
</li>
<li><p>Join a <a target="_blank" href="https://www.freecodecamp.org/news/learn-sql-free-relational-database-courses-for-beginners/">comprehensive course on databases</a>. Learn about SQL and relational databases like <a target="_blank" href="https://www.freecodecamp.org/news/learn-mysql-beginners-course/">MySQL</a>. Practice creating and managing databases.</p>
</li>
<li><p>Learn about server-side programming languages. Start with <a target="_blank" href="https://www.freecodecamp.org/news/the-php-handbook/">PHP</a> or <a target="_blank" href="https://www.freecodecamp.org/news/python-back-end-development-the-beginners-guide/">Python</a>. Learn basic syntax, control structures, and data types.</p>
</li>
</ul>
<h3 id="heading-step-2-advanced-backend-concepts"><strong>Step 2: Advanced Backend Concepts 🔋</strong></h3>
<ul>
<li><p>Deepen your understanding of databases. Explore <a target="_blank" href="https://www.freecodecamp.org/news/learn-nosql-in-3-hours/">NoSQL databases</a> like <a target="_blank" href="https://www.freecodecamp.org/news/crud-api-with-node-js-express-mongodb/">MongoDB</a>. Learn about data modeling and optimization.</p>
</li>
<li><p>Master server-side programming languages. Dig deeper into PHP or Python. Learn about functions, classes, and <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-oop-in-python/">object-oriented programming</a>.</p>
</li>
<li><p>Get hands-on projects with frameworks. Choose a popular framework like <a target="_blank" href="https://www.freecodecamp.org/news/build-a-google-drive-clone-with-laravel-php-vuejs/">Laravel</a> for PHP or <a target="_blank" href="https://www.freecodecamp.org/news/django-for-everybody-learn-the-popular-python-framework-from-dr-chuck/">Django</a> for Python. Build simple applications to understand the <a target="_blank" href="https://www.freecodecamp.org/news/model-view-architecture/">model-view-controller (MVC) architecture</a>.</p>
</li>
</ul>
<h3 id="heading-step-3-api-development-and-integration"><strong>Step 3: API Development and Integration 🛠️</strong></h3>
<ul>
<li><p>Learn about APIs and their importance in backend development. Explore <a target="_blank" href="https://www.freecodecamp.org/news/rest-api-design-best-practices-build-a-rest-api/">RESTful API design principles</a>.</p>
</li>
<li><p>Start building your own APIs. Use tools like <code>Postman</code> to <a target="_blank" href="https://www.freecodecamp.org/news/master-api-testing-with-postman/">test and debug API endpoints</a>. Learn about different <a target="_blank" href="https://www.freecodecamp.org/news/php-jwt-authentication-implementation/">authentication</a> <a target="_blank" href="https://www.freecodecamp.org/news/set-up-github-oauth-on-django-for-user-authentication/">methods</a> as well as <a target="_blank" href="https://www.freecodecamp.org/news/how-to-build-a-secure-django-web-app/">security</a>.</p>
</li>
<li><p>Focus on API integration. Learn how to consume APIs in web and mobile applications. Practice integrating third-party APIs into your projects.</p>
</li>
</ul>
<h3 id="heading-step-4-troubleshooting-and-optimization"><strong>Step 4: Troubleshooting and Optimization 🔮</strong></h3>
<ul>
<li>Master troubleshooting techniques. Learn how to diagnose and <a target="_blank" href="https://www.freecodecamp.org/news/python-debugging-handbook/">debug</a> backend applications effectively.</li>
</ul>
<ul>
<li><p>Jump into performance optimization techniques. Learn about <a target="_blank" href="https://www.freecodecamp.org/news/next-js-performance-optimization/">lazy loading</a>, <a target="_blank" href="https://www.freecodecamp.org/news/caching-vs-content-delivery-network/">caching</a>, <a target="_blank" href="https://www.freecodecamp.org/news/auto-scaling-and-load-balancing/">load balancing</a>, and <a target="_blank" href="https://www.freecodecamp.org/news/postgresql-indexing-strategies/">database indexing</a>.</p>
</li>
<li><p>Learn <a target="_blank" href="https://www.freecodecamp.org/news/how-to-set-up-monitoring-for-nodejs-applications-using-elastic/">monitoring</a> and analytics tools. Use tools like <a target="_blank" href="https://newrelic.com/">New Relic</a> or <a target="_blank" href="https://www.datadoghq.com/">Datadog</a> to monitor application performance. Learn how to generate and <strong>analyze</strong> performance metrics.</p>
</li>
</ul>
<h3 id="heading-step-5-cloud-infrastructure-and-deployment"><strong>Step 5: Cloud Infrastructure and Deployment 🌥️</strong></h3>
<ul>
<li><p>Understand <a target="_blank" href="https://www.freecodecamp.org/news/what-is-cloud-computing/">cloud computing</a> concepts. Learn about popular cloud providers like <a target="_blank" href="https://www.freecodecamp.org/news/free-107-hour-aws-cloud-project-bootcamp/">AWS</a> or <a target="_blank" href="https://www.freecodecamp.org/news/master-the-azure-devops-engineer-expert-certification-az-400/">Azure</a>.</p>
</li>
<li><p>Take a course on cloud services for backend development. Learn about <a target="_blank" href="https://www.freecodecamp.org/news/serverless-architecture-patterns-and-best-practices/">serverless computing</a>, <a target="_blank" href="https://www.freecodecamp.org/news/how-docker-containers-work/">containerization</a>, and <a target="_blank" href="https://www.freecodecamp.org/news/microservices-and-software-system-design-course/">microservices</a>.</p>
</li>
<li><p>Practice <a target="_blank" href="https://www.freecodecamp.org/news/how-to-deploy-node-js-app-on-azure/">deploying applications to the cloud</a>. Learn about <a target="_blank" href="https://www.freecodecamp.org/news/what-is-ci-cd/">CI/CD pipelines</a> and automated deployment strategies.</p>
</li>
</ul>
<h3 id="heading-step-6-advanced-topics-and-projects"><strong>Step 6: Advanced Topics and Projects 🚀</strong></h3>
<ul>
<li><p>Now you're ready to learn more advanced backend topics. Choose topics like <a target="_blank" href="https://www.freecodecamp.org/news/how-to-implement-message-queues-in-your-backend-applications/">message queues</a>, <a target="_blank" href="https://www.freecodecamp.org/news/implement-event-driven-architecture-with-react-and-fastapi/">event-driven architecture</a>, and <a target="_blank" href="https://www.freecodecamp.org/news/laravel-reverb-realtime-chat-app/">real-time communication</a>.</p>
</li>
<li><p>Work on a <a target="_blank" href="https://www.freecodecamp.org/news/backend-web-development-three-projects/"><strong>capstone project</strong></a>. Choose a challenging project that integrates various backend technologies and concepts.</p>
</li>
<li><p>Finally, reflect on your learning journey. Review your projects and identify areas for improvement. Prepare for job interviews by practicing <a target="_blank" href="https://www.freecodecamp.org/news/the-most-popular-coding-challenge-websites/"><strong>coding challenges</strong></a>.</p>
</li>
</ul>
<h2 id="heading-back-end-development-tools-and-software">Back-end Development Tools and Software</h2>
<p>Here's a breakdown of the tools and software commonly used in back-end development:</p>
<h3 id="heading-1-database-frameworks"><strong>1. Database Frameworks:</strong></h3>
<ul>
<li><p><strong>MySQL:</strong> A relational database management system used for storing and retrieving data. It's widely used for web applications and offers scalability and reliability.</p>
</li>
<li><p><strong>MongoDB:</strong> A NoSQL database program that uses JSON-like documents with schema flexibility. It's suitable for applications with rapidly changing data models or unstructured data.</p>
</li>
</ul>
<h3 id="heading-2-web-servers"><strong>2. Web Servers:</strong></h3>
<ul>
<li><p><strong>Node.js</strong>: Node.js is a cross-platform (meaning it supports multiple operating systems) JavaScript Runtime Environment that uses an event-driven, non-blocking I/O model. That means it can handle a large number of users at the same time. If you already know JavaScript, Node.js will likely be your best choice for building real-time applications like chat apps, online gaming apps, and collaborative tools.</p>
</li>
<li><p><strong>Apache HTTP Server 2:</strong> An open-source web server software that delivers web content across the internet. It's known for its stability, security, and flexibility, making it a popular choice for hosting websites and web applications.</p>
<p>  If your team is used to using languages like PHP or Python, Apache might be easier for them to work with.</p>
</li>
<li><p><strong>LiteSpeed</strong>: LiteSpeed is another web server software that helps websites handle lots of visitors without slowing down or crashing. It’s great for businesses that expect a lot of traffic, like during busy times. LiteSpeed also works with many programming languages like Python, Ruby, PHP, and Java.</p>
</li>
</ul>
<p>Imagine you're a company with 20 servers that can each handle 500 websites. Together, that’s 10,000 websites. But if you switch to LiteSpeed, you might be able to handle 20,000 websites with the same number of servers. That’s a big improvement!</p>
<p>When choosing a web server, it depends on what kind of website or app you’re building. If you’re just starting out, try Node.js first. It’s simple because you only need to learn one language (JavaScript) to build both the front part and the back part of your website.</p>
<h3 id="heading-3-security-protocolshttpswwwtheknowledgeacademycomblogwhat-is-apache"><a target="_blank" href="https://www.theknowledgeacademy.com/blog/what-is-apache/"><strong>3. Security Protocols:</strong></a></h3>
<ul>
<li><a target="_blank" href="https://www.theknowledgeacademy.com/blog/what-is-apache/"><strong>SSL/TLS Certificates:</strong> These are cryptographic protocols that provide secure commun</a>ication over a computer network. SSL (Secure Sockets Layer) and its successor TLS (Transport Layer Security) encrypt data between the server and client, ensuring confidentiality and integrity in online connections.</li>
</ul>
<h3 id="heading-4-version-control-system"><strong>4. Version Control System:</strong></h3>
<p>Next on your journey is to become familiar with version control systems. These systems help track project history and enable collaborative work with others.</p>
<ul>
<li>🔌 <a target="_blank" href="https://www.freecodecamp.org/news/gitting-things-done-book/">Learn Git</a>: Git is the most widely used version control system, employed by over 70% of software development teams. It's a must-know tool, and allocating around two weeks for learning Git is advisable.</li>
</ul>
<p>Back-end developers usually utilize these tools and software to build robust, scalable, and secure web applications that handle data storage, server hosting, and encryption of online communications.</p>
<p>If you seek more knowledge regarding backend development, you can check out this <a target="_blank" href="https://roadmap.sh/backend">in-depth visual guide to backend development</a>.</p>
<h3 id="heading-printable-roadmap">✅ Printable Roadmap</h3>
<p>You can also use this printable Backend Developer Notion template to track your progress.</p>
<p>Beginner developers often struggle with choosing the right tech stack which leads them to waste their time and often lose motivation.</p>
<p>To help you out, I created this easy-to-follow <a target="_blank" href="https://codewithshahan.gumroad.com/l/pcela">6-month backend developer roadmap</a> in Notion so that you can track your progress and stick with your goals in real-time.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j23rj7fwvut4fphzqud5.png" alt="Image of backend developer roadmap" width="600" height="400" loading="lazy"></p>
<p>This roadmap:</p>
<ul>
<li><p>🛤️ Provides a clear path to avoid confusion.</p>
</li>
<li><p>🎯 Helps you stay motivated by outlining where to start and end.</p>
</li>
<li><p>📚 Follows a structured plan, similar to a school syllabus.</p>
</li>
<li><p>📅 Organizes your learning with weekly goals for tools and languages.</p>
</li>
<li><p>⏳ Helps you get through it in 6 months, covering everything you need.</p>
</li>
<li><p>👀 Features a beautiful design for easy navigation.</p>
</li>
</ul>
<h2 id="heading-conclusion">👏 Conclusion</h2>
<p>By following this roadmap and dedicating consistent effort to learning, you can acquire valuable backend development skills and be well-prepared to land a job in backend development.</p>
<p>If you're curious about becoming a front-end developer as well, you can read this article as well. 👉 <a target="_blank" href="https://dev.to/codewithshahan/must-have-frontend-development-skills-roadmap-2024-28jc">The Roadmap to Become a Frontend Developer in 6 Months</a></p>
<p>If you ever wonder about <a target="_blank" href="https://dev.to/codewithshahan/the-future-of-frontend-development-1amd">the future of frontend development</a>, you can also take a look at this article.</p>
<p>Stay tuned for more valuable content, and if you find it helpful, you may also like my <a target="_blank" href="https://www.youtube.com/programmingwithshahan">YouTube Channel</a>.</p>
<p>🤳My Social: <a target="_blank" href="https://twitter.com/shahancd">X</a></p>
<p>Thanks for taking the time to read this article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a CRUD API – NodeJS and Express Project for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ An API is a technology that powers communication between software applications on the internet. API stands for Application Programming Interface, and it is basically a set of rules and protocols that define how different software can interact with ea... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-crud-api-project/</link>
                <guid isPermaLink="false">66ba305cf1ac6be9964fe7ac</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ crud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Express.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Victor Yakubu ]]>
                </dc:creator>
                <pubDate>Fri, 08 Mar 2024 11:04:53 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/Swimm-Images-4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>An API is a technology that powers communication between software applications on the internet. API stands for Application Programming Interface, and it is basically a set of rules and protocols that define how different software can interact with each other. </p>
<p>Imagine having two different programs: program A and program B. For these two programs to communicate together, an API is needed, and a set of rules ensure that they know what to expect when they interact with each other.</p>
<p>As a backend developer, your responsibilities involve building server-side applications, handling data storage, and providing the necessary functionalities to do all these through APIs. </p>
<p>There are <a target="_blank" href="https://blog.postman.com/different-types-of-apis/">different types of APIs</a> like REST, GraphQL, gRPC, SOAP, and WebSockets. However, when it comes to web development, one is more popular, and that is the <a target="_blank" href="https://www.freecodecamp.org/news/what-is-a-rest-api/">REST API</a>.</p>
<p>In this article, you will learn how to create a CRUD API with Node.js and Express using the REST architecture, and by the end of this article, you should have a fully functional API that is able to perform CRUD operations.</p>
<p>So, let's dive into the world of backend development with Node.js and Express and get started on our journey to building a CRUD API.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-what-is-a-crud-api">What is a CRUD API?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-nodejs">What is Node.js?</a></li>
<li><a class="post-section-overview" href="#heading-why-node">Why Node?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-install-nodejs">How to Install Node.js</a></li>
<li><a class="post-section-overview" href="#heading-what-is-express">What is Express?</a></li>
<li><a class="post-section-overview" href="#heading-why-do-you-need-express">Why do You Need Express?</a></li>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisite<strong>s</strong></a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-your-development-environment">How to Set Up Your Development Environment</a></li>
<li><a class="post-section-overview" href="#heading-how-to-set-up-a-server-for-your-crud-restful-api-with-nodejs-and-express">How to Set up a server for Your CRUD Restful API with Node.js and Express</a></li>
<li><a class="post-section-overview" href="#heading-crud-api-example">CRUD API Example</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-api-routes">How to Create API Routes</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-your-own-crud-api">How to Create Your own CRUD API</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-get-users-endpoint">How to Create the GET /users Endpoint</a></li>
<li><a class="post-section-overview" href="#heading-how-to-test-your-api-get-request">How to Test Your API GET Request</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-post-users-endpoint">How to Create the POST /users Endpoint</a></li>
<li><a class="post-section-overview" href="#heading-how-to-test-the-post-request">How to Test the POST Request</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-get-usersid-endpoint">How to Create the GET /users/:id Endpoint</a></li>
<li><a class="post-section-overview" href="#heading-how-to-test-the-get-request">How to Test the GET Request</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-delete-usersid">How to Create the DELETE /users/:id</a></li>
<li><a class="post-section-overview" href="#heading-how-to-test-the-delete-request">How to Test the DELETE Request</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-the-patch-usersid-endpoint">How to Create the PATCH /users/:id Endpoint</a></li>
<li><a class="post-section-overview" href="#heading-how-to-test-the-patch-request">How to Test the PATCH Request</a></li>
<li><a class="post-section-overview" href="#heading-wrapping-up">Wrapping UP</a></li>
</ul>
<h2 id="heading-what-is-a-crud-api">What is a CRUD API?</h2>
<p>In web development, CRUD operations are the bread and butter of backend systems. This is because they allow you to "Create", "Read", "Update", and "Delete" data through your API. </p>
<p>Here's a quick overview of the four primary HTTP methods associated with CRUD operations:</p>
<ul>
<li><strong>GET</strong>: Used for reading or retrieving data from the server.</li>
<li><strong>POST</strong>: Used for creating new data on the server.</li>
<li><strong>PUT</strong>: Used for updating existing data on the server.</li>
<li><strong>DELETE</strong>: Used for removing data from the server.</li>
</ul>
<p>Virtually every web application interacts with a database to perform these four core operations. Whether it's a social media platform, an e-commerce website, or a weather app, they all rely on creating, reading, updating, and deleting data. </p>
<p>For example, WhatsApp recently added an edit feature to the application, allowing users to make corrections to an already-sent message. That's one part of the CRUD operation in action (updating).</p>
<p>In the context of building a web API, these operations become the backbone of how your application interacts with data. Your API provides endpoints that allow client applications (like web or mobile apps) to perform these operations on the server. </p>
<p>This communication between the client and the server is the essence of web development, and understanding how to create a CRUD API is a crucial skill for a web developer.</p>
<h2 id="heading-what-is-nodejs">What is Node.js?</h2>
<p>Node.js is an open-source and cross-platform runtime environment for executing JavaScript code outside of a browser. Quite often, we use it to build back-end services, also called APIs. Node is ideal for building highly scalable, data-intensive and real-time back-end services that power our client applications</p>
<h2 id="heading-why-node">Why Node?</h2>
<ul>
<li>It is one of the most popular choices for building the backend.</li>
<li>You get to write JavaScript across your entire stack, making it easier to transition from either a frontend developer to a backend developer and vice versa.</li>
<li>It allows for easy scaling of applications, making it a good choice for large-scale professional projects.</li>
<li>It is fast and non-blocking. This is because of the asynchronous event-driven nature of Node.js.</li>
<li>Node.js has a vibrant community and a rich ecosystem of packages and libraries.</li>
</ul>
<h2 id="heading-how-to-install-nodejs">How to Install Node.js</h2>
<p>Installation steps:</p>
<ol>
<li>Download the Mac/Windows installer from the <a target="_blank" href="https://nodejs.org/en/download">Node.js website</a>.</li>
<li>Choose the Long-Term Support (LTS) version that’s shown on the left</li>
<li>After downloading, install/run the installer, and then follow the prompts. (You will have to click the NEXT button a bunch of times and accept the default installation settings</li>
<li>To confirm that Node has been successfully installed, open your terminal and run the command. (For Windows, you might need to restart your command before running it.)</li>
</ol>
<pre><code>node –version
</code></pre><h2 id="heading-what-is-express">What is Express?</h2>
<p>Express is a fast, unopinionated, and minimalist web backend or server-side web framework for Node.js. Basically, it gives you the ability to build your APIs how you want them, with less code.</p>
<p>It is a framework built on top of Node.js that allows you to create your Backend with ease. You can use Express in combination with frontend frameworks like React, Angular, or Vue to build full-stack applications.</p>
<h2 id="heading-why-do-you-need-express">Why do You Need Express?</h2>
<ul>
<li>It makes building web applications with Node.js much easier.</li>
<li>It is extremely light, fast and free.</li>
<li>It is used for both server-rendered apps as well as API/Microservices.</li>
<li>It is the most popular Node.</li>
<li>It gives you full control over requests and responses.</li>
</ul>
<h2 id="heading-prerequisites">Prerequisite<strong>s</strong></h2>
<p>To follow along, you'll need to have the following:</p>
<ul>
<li>Basic knowledge of JavaScript</li>
<li>Download and install <a target="_blank" href="https://nodejs.org/en">Node.js</a> and <a target="_blank" href="https://www.postman.com/downloads/">Postman</a> on your computer</li>
</ul>
<p>See the complete code for this tutorial on <a target="_blank" href="https://github.com/Aviatorscode2/crud-api-tutorial">Github</a>.</p>
<h2 id="heading-how-to-set-up-your-development-environment">How to Set Up Your Development Environment</h2>
<p>Before diving into creating your API, let's go through the process of creating a basic server on your local computer. </p>
<p>Here are the steps to follow:</p>
<h3 id="heading-step-1-create-directory">Step #1 – Create Directory</h3>
<p>Create a directory/folder on your computer. Open the folder in a code editor</p>
<h3 id="heading-step-2-create-indexjs-file">Step #2 – Create index.js File</h3>
<p>Create an <strong>index.js</strong> file inside the folder using this command:</p>
<pre><code>touch index.js
</code></pre><h3 id="heading-step-3-initialize-npm">Step #3 – Initialize NPM</h3>
<p>Initialize NPM inside the folder by running this command in your terminal:</p>
<pre><code>npm init -y
</code></pre><p>The command will create a <strong>package.json</strong> file with default values.</p>
<h3 id="heading-step-5-install-express">Step #5 – Install Express</h3>
<p>Use the command below to install Express.js</p>
<pre><code>npm install express
</code></pre><p>After installing Express, go to the <strong>package.json</strong> file and include <strong>“type”: “module”</strong>. This declaration will tell Node that this project will be using <a target="_blank" href="https://nodejs.org/api/packages.html#type">ES6 module syntax</a> (import/export) instead of common.js, which is the default in Node.  </p>
<p><img src="https://lh7-us.googleusercontent.com/s0sHrHSK7ulqOU4Ddw6WzER6waGEGaCxV26mk-ieuqDVKYBZSKlJ1aDW8WXbCOlfzC1xcW8lXh1-HVSNnYUXYM3MRmmy0N-6uQh-J3qDnjHtxB5atRbJQ-cxR1AWzLTa9RTwv_cXNXpNGz3lbSBHejM" alt="Image" width="1600" height="601" loading="lazy">
<em>package.json file with <code>type:module</code></em></p>
<h2 id="heading-how-to-set-up-a-server-for-your-crud-restful-api-with-nodejs-and-express">How to Set up a server for Your CRUD Restful API with Node.js and Express</h2>
<p>To create a CRUD <a target="_blank" href="https://www.freecodecamp.org/news/what-is-rest-rest-api-definition-for-beginners/#:~:text=An%20API%20that%20complies%20with%20some%20or%20all%20of%20the%20six%20guiding%20constraints%20of%20REST%20is%20considered%20to%20be%20RESTful.">restful</a> API, you first need to set up your server. You can do this by following these steps:</p>
<h3 id="heading-step-1-write-your-server-application-code-inside-the-indexjs-file">Step #1 – Write your Server Application Code inside the index.js file</h3>
<p>Basically, a server code will look like this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> bodyParser <span class="hljs-keyword">from</span> ‘body-parser

<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">5000</span>

app.use(bodyParser.json());

app.listen(PORT, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running on port: http://localhost:<span class="hljs-subst">${PORT}</span>`</span>));
</code></pre>
<p>Here's an explanation for the code above:</p>
<ul>
<li>In the first line, we imported <code>express</code> from the Express module that we installed.</li>
<li>The <code>bodyParser</code> comes with Express, and it allows us to take in the incoming POST request body.</li>
<li>Next, we created an <code>app</code> using the <code>express</code> object.</li>
<li>We then specified the port for the application – it was set to <strong>5000</strong> (if you get an error using this port, it might be that the port is currently being used by a different app, so you can either change your port or stop the other app from using the port).</li>
<li>Next, we specified that JSON data will be used in the application.</li>
<li>Once that was created, we used the <code>listen</code> method on the <code>app</code> to make our application listen for incoming requests. The method accepts two things: the <strong>PORT</strong>, which is where we would be listening for requests from our client side, and a callback function that will be triggered when our server is set up.</li>
</ul>
<h3 id="heading-step-2-start-the-server">Step #2 – Start the Server</h3>
<p>Now you can start your server by running this command. If you used a different file, replace index.js with the file name where the server is located.</p>
<pre><code>node index.js
</code></pre><p>Now your server should be running on <strong>port 5000</strong>. You can verify that your server is running on your terminal</p>
<h3 id="heading-step-3-install-nodemon-optional">Step #3 – Install Nodemon (Optional)</h3>
<p>At the moment, anytime you make changes to your server file, you will need to restart the server before your changes can reflect (you can try it and see). So to take care of this challenge, you can use Nodemon. Run the command to install it:</p>
<pre><code>npm install nodemon
</code></pre><p>To use Nodemon, head over to your <strong>package.json</strong> file and set up a script. Replace your start script with this instead:</p>
<pre><code><span class="hljs-string">"start"</span>: <span class="hljs-string">"nodemon index.js"</span>
</code></pre><p>Note that <strong>index.js</strong> is the file where the server code is written.</p>
<p>Now you can start your server by running this command:</p>
<pre><code>npm start
</code></pre><p>With this code, we've set up a server that listens on port 5000 and prints a message when it starts. But this is just the beginning because our server needs to do much more. </p>
<p>Let's explore how to handle API requests next.</p>
<h2 id="heading-crud-api-example">CRUD API Example</h2>
<p>Let's start by defining the API routes for each CRUD operation. These routes will serve as the entry points for your API, and they will map to specific actions we want to perform on our data. </p>
<p>In our case, these actions are creating, reading, updating, and deleting data.</p>
<h2 id="heading-how-to-create-api-routes">How to Create API Routes</h2>
<p>When the port (<a target="_blank" href="http://localhost:5000/">http://localhost:5000/</a>) is opened in a browser, you will get an error.</p>
<p><img src="https://lh7-us.googleusercontent.com/p-3qnXzvHDxcsbhpYXO4VMopivQMhqgSPwSTXXDQJW_2GRhFFvkpL8JitNShGcrjyQiMx87ZwkK_4iEbs3JieTdRJQ13Q94O0hV7U9mwOpcm9ET7Yngb2TXQpItUrpepYzeXzg4rZMGdnxonhMREHAo" alt="Image" width="1600" height="905" loading="lazy">
<em>localhost:5000 in the browser without any routes</em></p>
<p>This is because Node.js and Express are all about routing, and we don't any routes yet. </p>
<p>You can define API routes using the <code>app.get()</code>, <code>app.post()</code>, <code>app.put()</code>, and <code>app.delete()</code> methods in your Express application (in the <strong>index.js</strong> file). </p>
<p>Here's how to create a route to handle GET requests using the <code>app.get()</code> function:</p>
<pre><code>app.get(<span class="hljs-string">'/'</span>, (req, res)
</code></pre><p>The <code>app.get()</code> function accepts two parameters. The first is used to specify the path (in this case, it is '/'). </p>
<p>The next parameter is a callback function where you define what happens when the GET request is called. The function also has <a target="_blank" href="https://www.freecodecamp.org/news/express-explained-with-examples-installation-routing-middleware-and-more/">two parameters</a>: the request body (<code>req</code>), which can contain information such as the request query string, parameters, body, and HTTP headers. While the response object (<code>res</code>) contains the information you want to send </p>
<p>Here is the complete code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> bodyParser <span class="hljs-keyword">from</span> <span class="hljs-string">'body-parser'</span>
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">5000</span>;

app.use(bodyParser.json());

app.get(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'[GET ROUTE]'</span>);
    res.send(<span class="hljs-string">'HELLO FROM HOMEPAGE'</span>);
})

app.listen(PORT, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running on port: http://localhost:<span class="hljs-subst">${PORT}</span>`</span>));
</code></pre>
<p>When you head back to <a target="_blank" href="http://localhost:5000/">http://localhost:5000/</a> and refresh it, you shouldn’t get an error anymore.</p>
<p><img src="https://lh7-us.googleusercontent.com/6289p5Vl_k4v2ULLd5iUVCpr-sykpbcEytcHsqoJZTB4MgWgDEfVuH1_4aTt0w9ThAhFNCn_rMrlwNFB2hfgOKWQ3znH3MHnHRxh0sd1czb_ntBHMIWS6HtAIo3yuCgDEFK7RVFGvTel0s89T3qTKjc" alt="Image" width="1600" height="905" loading="lazy">
<em>localhost:5000 in the browser with GET route</em></p>
<h2 id="heading-how-to-create-your-own-crud-api">How to Create Your own CRUD API</h2>
<p>For this API, you will be handling a set of users. Handling users in a database is a great example because it is a common use case in most applications. </p>
<p>Here are the API endpoints you will be creating:</p>
<ol>
<li>GET /users - find all users</li>
<li>POST /users - creates a user</li>
<li>GET /users/:id - finds a specific user</li>
<li>DELETE /users/:id - deletes a specific user</li>
<li>PATCH /users/:id - updates a specific user.</li>
</ol>
<h3 id="heading-how-to-create-the-get-users-endpoint">How to Create the GET /users Endpoint</h3>
<p>Reading data is one of the most common operations in an API. In this example, you will be getting the list of all the users in your mock database. This information will be presented in JSON format.</p>
<p>To define a route to retrieve users' data from the database, follow these steps:</p>
<ul>
<li>Create a new folder called routes</li>
<li>Create a new file called <strong>users.j</strong>s inside the routes folder.</li>
<li>Write the code to set up the GET router.</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">const</span> router = express.Router();

<span class="hljs-comment">// Mock database</span>
<span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'John'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Doe'</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">'johndoe@example.com'</span>,
  },
  {
    <span class="hljs-attr">first_name</span>: <span class="hljs-string">'Alice'</span>,
    <span class="hljs-attr">last_name</span>: <span class="hljs-string">'Smith'</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">'alicesmith@example.com'</span>,
  },
];

<span class="hljs-comment">// Getting the list of users from the mock database</span>
router.get(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.send(users);
})

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router
</code></pre>
<p>In this code snippet:</p>
<ul>
<li><code>import express from 'express';</code> imports the Express.js framework</li>
<li><code>const router = express.Router();</code> creates a fresh router instance, stored in the variable router.</li>
<li>The <code>users</code> variable serves as the mock database containing an array of users.</li>
<li>The <code>router.get()</code> function sets up a route that responds to HTTP GET requests.</li>
<li>The second part of the code <code>(req, res) =&gt; { ... }</code> is a callback function. It gets executed when a request is made to the GET route.</li>
<li>Inside the callback function, we used <code>res.send(users)</code> to send a response back to the client. In this example, we're sending the <code>users</code> variable as the response. So when a user hits the GET URL, the server responds by sending the data inside the <code>users</code> variable in JSON format to the client.</li>
</ul>
<p>Save your changes in the <strong>users.js</strong> file. Then do the following in the <strong>index.js</strong> file:</p>
<p>import your user routes from <strong>user.js</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> userRoutes <span class="hljs-keyword">from</span> <span class="hljs-string">'./routes/users.js'</span>
</code></pre>
<p>Use the <code>app.use</code> method, and specify the path and router handler:</p>
<pre><code class="lang-javascript">app.use(<span class="hljs-string">'/users'</span>, userRoutes);
</code></pre>
<p>When a user visits <a target="_blank" href="http://localhost:5000/users">http://localhost:5000/users</a>, the router is triggered. It effectively acts as a filter, determining when a specific set of routes should be applied.</p>
<p>Here is the complete code for the <strong>index.js</strong> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> bodyParser <span class="hljs-keyword">from</span> <span class="hljs-string">'body-parser'</span>
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">import</span> userRoutes <span class="hljs-keyword">from</span> <span class="hljs-string">'./routes/users.js'</span>

<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">5000</span>;

app.use(bodyParser.json());

app.use(<span class="hljs-string">'/users'</span>, userRoutes);

app.get(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> res.send(<span class="hljs-string">'HELLO FROM HOMEPAGE'</span>))

app.get(<span class="hljs-string">'/'</span>, (req, res));

app.listen(PORT, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server running on port: http://localhost:<span class="hljs-subst">${PORT}</span>`</span>));
</code></pre>
<h4 id="heading-how-to-test-your-api-get-request"><strong>How to Test Your API GET Request</strong></h4>
<p>You can use either a browser (browsers can only be used to perform GET requests) or Postman to test the GET request. </p>
<p>So copy your API URL, <a target="_blank" href="http://localhost:5000/users">http://localhost:5000/users</a>, and paste it either on Postman or in your browser. If you are using Postman, you will first need to make a GET request, then paste your API URL, and then click on send. After that, you will see the list of users in your Postman console.</p>
<p><img src="https://lh7-us.googleusercontent.com/XBhjewUFTBvBhc2larsYwqzS3-RHp7qFBrO4lvScf91EUFO5TEgt83iU48h9ArDK3EbrPwdS7_-WkI51JkDUHH4v2U9pWXdYMSbKeCpQrYRunvhuvAIAadzcAyj8y0hojjxs1CIlAo7TigoTJrM3y5c" alt="Image" width="1600" height="905" loading="lazy">
<em>postman GET route test</em></p>
<h3 id="heading-how-to-create-the-post-users-endpoint">How to Create the POST /users Endpoint</h3>
<p>You can use the POST request to add data to your database. It accepts input from the client and stores it in the database. To create data in our API, we'll define a route that accepts POST requests and saves the data to the mock database you have set up. </p>
<p>But before that, you'll need the UUID package. Use this command to install it:</p>
<pre><code>npm install uuid
</code></pre><p>This package will help generate a unique ID for each user you will be creating. This will be useful when you are implementing the GET, DELETE, and PATCH user by ID requests, where you will need a way to identify a specific user.</p>
<p>So in the <strong>users.js</strong> file, do the following:</p>
<p>Import the <code>uuid</code> package:</p>
<pre><code><span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;
</code></pre><p>Secondly, you'll have to implement the code for the POST request. </p>
<p>Here is what it looks like:</p>
<pre><code class="lang-javascript">router.post(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> user = req.body;

    users.push({ ...user, <span class="hljs-attr">id</span>: uuidv4() });

    res.send(<span class="hljs-string">`<span class="hljs-subst">${user.first_name}</span> has been added to the Database`</span>);
})
</code></pre>
<p>In the code snippet:</p>
<ul>
<li>The <code>router.post()</code> function sets up a route that responds to HTTP POST requests. This means that when a client sends a POST request to the root URL of your application, this route will be triggered.</li>
<li>Within the callback function <code>(req, res) =&gt; { ... }</code>, we access the <code>req</code> object, which represents the incoming request made by the client. Specifically, we're interested in the <code>req.body</code> property. This property contains the data (first name, last name, and email) that the client will send as part of the POST request's body.</li>
<li>With <code>const user = req.body</code> we extract this data from <code>req.body</code> and store it in the <code>user</code> variable.</li>
<li>Next, we added the <code>user</code> data to an array called <code>users</code>. To ensure each user has a unique identifier, we generate a universally unique identifier (UUID) using a function like <code>uuidv4()</code> and include it as id in the user object. This helps in keeping user records distinct and identifiable.</li>
<li>Finally, we used <code>res.send()</code> to send a response back to the client. In this case, we're sending a simple message notifying the client that the user has been successfully added to the database. The message includes the user's first name for a personalized touch.</li>
</ul>
<p>Here is the complete code</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">'express'</span>;
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;

<span class="hljs-keyword">const</span> router = express.Router();

<span class="hljs-keyword">const</span> users = [];

<span class="hljs-comment">// Adding users to our mock database</span>

router.post(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> user = req.body;

    users.push({ ...user, <span class="hljs-attr">id</span>: uuidv4() });

    res.send(<span class="hljs-string">`<span class="hljs-subst">${user.first_name}</span> has been added to the Database`</span>);
})  

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router
</code></pre>
<h4 id="heading-how-to-test-the-post-request"><strong>How to Test the POST Request</strong></h4>
<p>Here are the steps to follow to make a POST request on Postman:</p>
<ul>
<li>Go to Postman</li>
<li>Open a new request tab</li>
<li>Select "POST" from the list of available HTTP methods</li>
<li>In the URL field, enter the full URL where you want to send the POST request (<a target="_blank" href="http://localhost:5000/users">http://localhost:5000/users</a>)</li>
<li>Click on the "Body" tab in the request window.</li>
<li>Choose the format in which you want to send your POST data (choose JSON).</li>
<li>Enter the data you want to send in the request body. This data should match the format expected by the server.</li>
<li>Finally, click on “Send”  </li>
</ul>
<p><img src="https://lh7-us.googleusercontent.com/olNqMdggCcvhUotN9ospAjg8r7t-HE_3yUqGrEkf_dKnCGTwFiKWQJB3x4dccUbHPlYbP-j8S7a2xBG3TpMvceVdmz_nC8zRtaRQzfeknyyo-OQJDwuSFZJkWPiQctDkoTYfZCsVnE1ljQN96Hxow54" alt="Image" width="1600" height="905" loading="lazy">
<em>postman POST route test</em></p>
<p>If it is successful, you will get a response saying, “Daanny has been added to the database."</p>
<p>To confirm if it has been added, make a GET request, and you should see the new user added to your database. (Note: This user information will be lost when your server restarts since it’s not saved to an actual database).</p>
<p><img src="https://lh7-us.googleusercontent.com/cHmJ3hcsMb5Vnj9zh_kSdqBMRrgtR1pQJ3-_DgHgukwdtyLrnG5AN0jyL4gGtzyTYUJj4w_ENO6ZqVsMZLqdnRytOgP4tR5A2B2T_TnDHNbRDEb9JAGF7SmTwVVwBczzg02JmLfWAucyeyMlnPs1Ehg" alt="Image" width="1152" height="652" loading="lazy">
<em>postman GET route test</em></p>
<h3 id="heading-how-to-create-the-get-usersid-endpoint">How to Create the GET /users/:id Endpoint</h3>
<p>Fetching specific data based on a unique identifier, such as a user ID, is a common operation. It's often essential for building features like user profiles or retrieving individual records from a database. </p>
<p>In this section, you’ll explore how to use this endpoint (users/:id) to retrieve user information based on a provided user ID. </p>
<p>Let's get started!</p>
<pre><code class="lang-javascript">router.get(<span class="hljs-string">'/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> { id } = req.params;

    <span class="hljs-keyword">const</span> foundUser = users.find(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> user.id === id)

    res.send(foundUser)
});
</code></pre>
<p>Here's what this code snippet does:</p>
<ul>
<li>The <code>router.get()</code> function sets up a route that responds to HTTP GET requests. In this example, we've defined a route with ('/:id'). The :id part is a route parameter, which allows us to capture a dynamic value from the URL. In this case, it represents the user ID we want to retrieve.</li>
<li>Within the callback function <code>(req, res) =&gt; { ... }</code>, we can access the <code>req</code> object, which represents the incoming request made by the client. Specifically, we're interested in <code>req.params</code>, which holds the values of route parameters. In this case, we destructure <code>id</code> from <code>req.params</code>, effectively extracting the user ID from the URL. For example, if a client makes a GET request to /users/123, the id will be '123'.</li>
<li>We used the <code>.find()</code> method to search through this data based on the user ID (id) captured from the URL. This method attempts to find a user whose ID matches the provided id.</li>
<li>Once we located the user data (if it exists), we send it as the response using <code>res.send(foundUser)</code>. The <code>foundUser</code> variable contains the user object that matches the requested ID.</li>
</ul>
<h4 id="heading-how-to-test-the-get-request"><strong>How to Test the GET Request</strong></h4>
<p>In testing the API, follow these steps:</p>
<ul>
<li>Go to your POST request tab and make as many requests as you want to add a new user to the database.</li>
<li>Go to your GET request tab and make a request to see the list of users you have added</li>
</ul>
<p><img src="https://lh7-us.googleusercontent.com/qEuvm-1QKHvGmFCmru5dF2b9JSW5ua_dMcovZaKFZL_NChfSQqaazX4QvvSrSkjMzTO9Yqon5zhsZ5ZZwrWO0WifthlOKfboojC6ws8Fju2HK5TcE1oLvZZhOaO5xljRIUvYt_oun_NsIH13sq2Yf0o" alt="Image" width="1600" height="905" loading="lazy">
<em>postman GET route test</em></p>
<ul>
<li>Copy the id of any of the users on the list</li>
<li>Create a new GET request tab, copy in the base API URL, and add the id of any of the users to it. It should be in a format like this: <a target="_blank" href="http://localhost:5000/users/734a9e75-b3f5-415f-82fb-79b4fdf1a593">http://localhost:5000/users/734a9e75-b3f5-415f-82fb-79b4fdf1a593</a></li>
<li>Click on “Send”. If it’s successful, you will see the user information of the user id you used for the request</li>
</ul>
<p><img src="https://lh7-us.googleusercontent.com/ui9cj6HDXIifMjzlnICvnzgIGOssvRbGeCrlos2DXG541b4r9Dsn0mVrXZBfyCwvO6gh3yovrbsDD1I7EU0-5j7r3fRIrQ4XFX1QR-vlFJlXuXb1Ht753re7ZDf2cC7VyPyLgee6a6gZmwjnkCb8RI0" alt="Image" width="1600" height="905" loading="lazy">
<em>postman GET route test</em></p>
<h3 id="heading-how-to-create-the-delete-usersid">How to Create the DELETE /users/:id</h3>
<p>Sometimes, it's necessary to remove user accounts or specific records from a database for various reasons, such as account deactivation. </p>
<p>Here, you will explore how to use this endpoint to delete user data based on a provided user ID.</p>
<p>To delete data, we'll define a route that accepts DELETE requests and removes the data from the database.</p>
<p>See the code to delete a user from a database below</p>
<pre><code class="lang-javascript">router.delete(<span class="hljs-string">'/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { id } = req.params;

  users = users.filter(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> user.id !== id)

  res.send(<span class="hljs-string">`<span class="hljs-subst">${id}</span> deleted successfully from database`</span>);
});
</code></pre>
<p>Here's what this code does:</p>
<ul>
<li>The <code>router.delete()</code> function sets up a route that responds to HTTP DELETE requests. In this example, we've defined a route with ('/:id'), where :id is a route parameter. It captures a dynamic value from the URL, representing the user ID we want to delete.</li>
<li>In the callback function <code>(req, res) =&gt; { ... }</code>, we can access the <code>req</code> object, which represents the incoming request made by the client. Specifically, we're interested in <code>req.params</code>, which holds the values of route parameters. Here, we destructure id from <code>req.params</code>, extracting the user ID from the URL. For instance, if a client sends a DELETE request to /users/123, id will be '123'.</li>
<li>Assuming that we have an array or database (users) containing user data, we employ the <code>.filter()</code> method to create a new array that excludes the user with the matching ID (id). This effectively removes the user from the data store.</li>
<li>After successfully deleting the user, we send a response back to the client using <code>res.send()</code>. The response contains a message confirming the deletion, including the user's ID that was deleted from the database.</li>
</ul>
<h4 id="heading-how-to-test-the-delete-request"><strong>How to Test the DELETE Request</strong></h4>
<p>Here are the steps to delete a user from the database on Postman:</p>
<ul>
<li>Go to Postman</li>
<li>Open a new request tab</li>
<li>Select "DELETE" from the list of available HTTP methods</li>
<li>Enter the URL. It should contain the id of the user you want to delete (for example: <a target="_blank" href="http://localhost:5000/users/734a9e75-b3f5-415f-82fb-79b4fdf1a593">http://localhost:5000/users/734a9e75-b3f5-415f-82fb-79b4fdf1a593</a>). If you don’t have a user in your database, you will need to create one and copy the id.</li>
<li>Click on “Send”.  </li>
</ul>
<p><img src="https://lh7-us.googleusercontent.com/bTO6dcTaujyxm7ruPcyCJTzMfZemFop1oqU803Fif2kCeq1Z2q3uB1-JHB1aK4-ePIimPvb1LBYuty8_YFd7xP_i8UVhFZewWHlmwKy3MlWssMWtdaBnXtCkyB8NZebDnldJzRXc_v0Fs7MS4rZJq_g" alt="Image" width="1600" height="905" loading="lazy">
<em>postman DELETE route test</em></p>
<p><img src="https://lh7-us.googleusercontent.com/B9YHqAtEyg1f0O0CAojNJDXjK212LCxFodc9Ld3j04bdZsK9R5qHExSxaKGCAqgI0W79jHJ2bN3l9GkVgB3DYAd192zB9LzThvcAZJFuXoBO5JUqcUKWyBWcc6q4KirQA4B6Hi6t1NN3eU8e-dH10pY" alt="Image" width="1152" height="652" loading="lazy">
<em>postman DELETE route test</em></p>
<h3 id="heading-how-to-create-the-patch-usersid-endpoint">How to Create the PATCH /users/:id Endpoint</h3>
<p>There are times when you don't need to update an entire resource or object. Instead, you'd want to make partial modifications or adjustments. This is where the HTTP PATCH request comes into play.</p>
<p>For example, after creating a new user, you can change either the first name, last name, or email of that user using the PATCH request. Let’s see how to do that.</p>
<pre><code class="lang-javascript">router.patch(<span class="hljs-string">'/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { id } = req.params;

  <span class="hljs-keyword">const</span> { first_name, last_name, email} = req.body;

  <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> user.id === id)

  <span class="hljs-keyword">if</span>(first_name) user.first_name = first_name;
  <span class="hljs-keyword">if</span>(last_name) user.last_name = last_name;
  <span class="hljs-keyword">if</span>(email) user.email = email;

  res.send(<span class="hljs-string">`User with the <span class="hljs-subst">${id}</span> has been updated`</span>)

});
</code></pre>
<p>Here's what this code snippet accomplishes:</p>
<ul>
<li>The <code>router.patch()</code> function sets up a route that responds to HTTP PATCH requests. In this example, we've defined a route with ('/:id'), where :id is a route parameter. It captures the dynamic value from the URL, representing the user ID we want to update.</li>
<li>Within the callback function <code>(req, res) =&gt; { ... }</code>, we can access the <code>req</code> object, which represents the incoming request made by the client. Specifically, we're interested in <code>req.params</code>, which hold the values of route parameters (id in this case), and <code>req.body</code>, which contains the data to be updated.</li>
<li>Next, we used <code>.find()</code> to locate the user object with the matching ID (id). Once found, we can proceed to modify the user's data based on the content of <code>req.body</code>. We also checked if first_name, last_name, or email properties exist in <code>req.body</code>. If they do, we can update the corresponding properties of the user object with the new values. This allows us to make selective changes to the user's data without affecting other attributes.</li>
<li>After successfully applying the requested modifications, we send a response back to the client using <code>res.send()</code>. The response includes a message confirming the successful update of the user data, along with the user's ID.</li>
</ul>
<h4 id="heading-how-to-test-the-patch-request"><strong>How to Test the PATCH Request</strong></h4>
<p>Follow these steps to make a PATCH request in Postman:</p>
<ul>
<li>Go to Postman</li>
<li>Open a new request tab</li>
<li>Select "PATCH" from the list of available HTTP methods</li>
<li>Enter URL; the URL will contain the id of the user you want to delete (for example: <a target="_blank" href="http://localhost:5000/users/734a9e75-b3f5-415f-82fb-79b4fdf1a593">http://localhost:5000/users/734a9e75-b3f5-415f-82fb-79b4fdf1a593</a>). If you don’t have a user in your database, you will need to create one and copy the id.</li>
<li>Click on the "Body" tab in the request window and choose the format in which you want to send your PATCH data (for example: JSON, form-data, x-www-form-urlencoded).</li>
<li>Enter the data you want to send in the request body. This data should only include the specific changes you want to make to the resource.</li>
<li>Then click the "Send" button. Postman will send the PATCH request to the specified URL with the provided data.</li>
</ul>
<p><img src="https://lh7-us.googleusercontent.com/K1OH_u-2DOJbkMqlQ3uJow9XNKh0iOmE8fedCCspUiQIHcvm-DmIorFvZcApoDWGSK4YMkFR7RtcHBmzMZaJUyXy7SMDJWxH_PDLFmugGPNQDmKzM6HE3tPOBQZaS1388bZzLlmcTThQa_wy1ZPrm1g" alt="Image" width="1600" height="905" loading="lazy">
<em>postman PATCH route test</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>APIs are the linchpin connecting various software components and enabling them to work together seamlessly. They allow them to communicate, share data, and perform tasks. In the context of web development, APIs enable the web to function as we know it today.</p>
<p>In this tutorial, we explored backend development by creating a CRUD API with Node.js and Express. We covered various concepts, like how to set up a development environment, create a server with Express and Node.js, and most importantly, how to handle CRUD operations and test your API using Postman.</p>
<p>While we've covered fundamental aspects of API creation in this tutorial, there is still a vast landscape of knowledge to explore as regards to APIs. These include how to secure your API by adding authentication, how to use middleware, database interaction, API deployment, and a lot more.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Communication Design Patterns for Backend Development ]]>
                </title>
                <description>
                    <![CDATA[ By Chinwendu Enyinna When you’re building the backend of an application, you’ve got to figure out how all the different components are going to talk to each other.  It’s like setting up a communication network for your app’s brain, and the way you do... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/communication-design-patterns-for-backend-development/</link>
                <guid isPermaLink="false">66d45e01bc9760a197a10370</guid>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Backend Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ design patterns ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 12 Sep 2023 16:25:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/comm-design-patterns.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Chinwendu Enyinna</p>
<p>When you’re building the backend of an application, you’ve got to figure out how all the different components are going to talk to each other. </p>
<p>It’s like setting up a communication network for your app’s brain, and the way you do it can seriously impact how well your app performs.</p>
<p>But here’s the fun part: there’s no one-size-fits-all answer. The communication pattern you choose depends on what your application needs to do. </p>
<p>So, in this tutorial, we’re going to take a look at five different ways backend systems like to chat it up. We’ll explore what they’re good at and when you should invite them to the conversation. Let’s dive right in!</p>
<h2 id="heading-what-is-a-design-pattern">What is a Design Pattern?</h2>
<p>Before we get into all the cool patterns, let’s talk about what a design pattern is, shall we?</p>
<p><strong>Design patterns</strong> are nifty, tried-and-true reusable solutions to common problems encountered during software design and development. You can call them the cheat codes of software design and development. </p>
<p>They can help provide a structured approach to solving recurring challenges, offering a set of guidelines and best practices that can be adapted for various scenarios.</p>
<p>Now that we’ve got that down, let’s explore five of these emerging design patterns used for backend communication.</p>
<h2 id="heading-request-response-pattern">Request-Response Pattern</h2>
<p>The request-response pattern is a fundamental building block for how the front-end and back-end of web applications chat with each other. This pattern is like a conversation between the client (say your browser) and the server, where they take turns speaking. Imagine it as a “ping-pong” of data.</p>
<p>Here's a diagram illustrating what that looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Untitled-2023-08-13-1619.png" alt="Image" width="600" height="400" loading="lazy">
<em>request/response communication model</em></p>
<p><img src="https://cdn-images-1.medium.com/max/800/1*SQDgiDS9Ouqi7tksE9744w.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-does-the-request-response-pattern-work">How does the Request-Response pattern work?</h3>
<p>This pattern is all about synchronization. The client sends a request to the server, kind of like raising your hand to ask a question in class. Then it patiently waits for the server to respond before it can move on. </p>
<p>It’s like a polite conversation — one speaks, the other listens, and then they swap roles.</p>
<p>You’ve probably heard of RESTful APIs, right? Well, they’re a prime example of the request-response model in action. </p>
<p>When your app needs some data or wants to do something on the server, it crafts an HTTP request — say GET, POST, PUT, or DELETE (like asking nicely for a page), and sends it to specific endpoints (URLs) on the server. The server then processes your request and replies with the data you need or performs the requested action. </p>
<p>It’s like ordering your favorite dish from a menu — you ask, and the kitchen (server) cooks it up for you.</p>
<p>Interestingly, there’s more than one way to have this conversation. Besides REST, there’s GraphQL, an alternative that lets you ask for exactly the data you want. It’s like customizing your order at a restaurant — you get to pick and choose your ingredients.</p>
<p>It’s important to note that this pattern isn’t just limited to web applications. You’ll spot it in Remote Procedure Calls (RPCs), database queries (with the server being the client and the database, the server), and network protocols (HTTP, SMTP, FTP) to name a few. It’s like the language of communication for the web.</p>
<h3 id="heading-benefits-of-the-request-response-pattern">Benefits of the Request-Response pattern</h3>
<p><strong>Ease of Implementation and Simplicity:</strong> The way communication flows in this model is pretty straightforward, making it a go-to choice for many developers, especially when they’re building apps with basic interaction needs.</p>
<p><strong>Flexibility and Adaptability</strong> (One Size Fits Many): The request-response pattern seamlessly fits into a wide range of contexts. You can use it for making API calls, rendering web pages on the server, fetching data from databases, and more.</p>
<p><strong>Scalability:</strong> Each request from the client is handled individually, so the server can easily manage multiple requests at once. This is highly beneficial for high-traffic websites, APIs that get tons of calls, or cloud-based services.</p>
<p><strong>Reliability:</strong> Since the server always sends back a response, the client can be sure its request is received and processed. This helps maintain data consistency and ensures that actions have been executed as intended even during high-traffic scenarios.</p>
<p><strong>Ease of Debugging:</strong> If something goes wrong, the server kindly sends an error message with a status code stating what happened. This makes error handling easy.</p>
<h3 id="heading-limitations-of-the-request-response-pattern">Limitations of the Request-Response Pattern</h3>
<p><strong>Latency Problem:</strong> Because it’s a back-and-forth conversation, there’s often a waiting period. This amounts to idle periods and amplifies latency, especially when the request requires the server to perform time-consuming computing tasks.</p>
<p><strong>Data Inconsistency in Case of Failures:</strong> If a failure occurs after the server has processed the request but before the response is delivered to the client, data inconsistency may result.</p>
<p><strong>Complexity in Real-Time Communication:</strong> For applications that need lightning-fast real-time communication (like live streaming, gaming, or chat apps), this pattern can introduce delays and is therefore unsuitable for these use-cases.</p>
<p><strong>Inefficiency in Broadcasting:</strong> In scenarios where you need to send the same data to multiple clients at once (broadcast), this pattern can be a bit inefficient. It’s like mailing individual letters instead of sending one group message.</p>
<p>Here’s a code example that shows the request-response pattern using Nodejs.</p>
<p>First, we have the <code>server.js</code> file. Here we’ve set up the server to listen for incoming requests from the client.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">"http"</span>);

<span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
 res.statusCode = <span class="hljs-number">200</span>;
 res.setHeader(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/plain"</span>);

 <span class="hljs-comment">//check request method and receive data from client</span>
 <span class="hljs-keyword">if</span> (req.method === <span class="hljs-string">"POST"</span>) {
  <span class="hljs-keyword">let</span> incomingMessage = <span class="hljs-string">""</span>;
  req.on(<span class="hljs-string">"data"</span>, <span class="hljs-function">(<span class="hljs-params">chunk</span>) =&gt;</span> {
   incomingMessage += chunk;
  });

  <span class="hljs-comment">//write back message received from the client on the console</span>
  req.on(<span class="hljs-string">"end"</span>, <span class="hljs-function">() =&gt;</span> {
   <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message from client: <span class="hljs-subst">${incomingMessage}</span>`</span>);
   res.end(<span class="hljs-string">`Hello client, message received!`</span>);
  });
 } <span class="hljs-keyword">else</span> {
  res.end(<span class="hljs-string">"Hey there,  Client!\n"</span>);
 }
});

<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">3030</span>;
server.listen(PORT, <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(
  <span class="hljs-string">`Server is listening for incoming request from client on port:<span class="hljs-subst">${PORT}</span>`</span>
 );
});
</code></pre>
<p>And here's the <code>client.js file</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">"http"</span>);

<span class="hljs-keyword">const</span> options = {
 <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
 <span class="hljs-attr">hostname</span>: <span class="hljs-string">"localhost"</span>,
 <span class="hljs-attr">port</span>: <span class="hljs-number">3030</span>,
 <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
};

<span class="hljs-comment">//message to server</span>
<span class="hljs-keyword">let</span> messageToServer = <span class="hljs-string">"Hey there, server!"</span>;

<span class="hljs-comment">//send a http request to the server</span>
<span class="hljs-keyword">const</span> req = http.request(options, <span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> {
 <span class="hljs-keyword">let</span> incomingData = <span class="hljs-string">""</span>;

 res.on(<span class="hljs-string">"data"</span>, <span class="hljs-function">(<span class="hljs-params">chunk</span>) =&gt;</span> {
  incomingData += chunk;
 });

 res.on(<span class="hljs-string">"end"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Response from the server: <span class="hljs-subst">${incomingData}</span>`</span>);
 });
});

req.on(<span class="hljs-string">"error"</span>, <span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Error message: <span class="hljs-subst">${error.message}</span>`</span>);
});

<span class="hljs-comment">//send message to the server</span>
req.write(messageToServer);

<span class="hljs-comment">//end your request</span>
req.end();
</code></pre>
<p>Here's the output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot--173-.png" alt="Image" width="600" height="400" loading="lazy">
<em>code output on the terminal</em></p>
<h2 id="heading-the-publishsubscribe-pattern">The Publish/Subscribe Pattern</h2>
<p>Publish/Subscribe is another communication design pattern you may see on the backend. It is used in distributed systems for asynchronous communication between several (usually decoupled) components. It’s perfect for when you’ve got a bunch of components that need to work together but want to keep their distance.</p>
<p>Here's a diagram showing how it works:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Untitled-2023-08-13-1619-9.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pub/Sub communication model</em></p>
<h3 id="heading-how-does-the-publishsubscribe-pattern-work">How does the Publish/Subscribe pattern work?</h3>
<p>This pattern involves the use of message queues (often called message brokers) which serve as intermediaries between the publishers and subscribers. These message brokers group messages into something called channels (or topics).</p>
<p>Publishers are the components that create and send messages while subscribers are the components that receive and consume the messages.</p>
<p>The publishers simply toss messages (or events) into specific channels/topics within the message broker. These channels act as the distribution point for the messages. The subscribers then indicate interest by subscribing to those channels within the message broker and whenever a message or event is published to that channel, they receive a copy.</p>
<p>Message queuing tools like Apache Kafka and MQTT use the publish/subscribe communication pattern under the hood.</p>
<h3 id="heading-benefits-of-the-publishsubscribe-pattern">Benefits of the Publish/Subscribe pattern</h3>
<p><strong>Asynchronous Communication:</strong> Unlike the request-response model, pub/sub is designed to be asynchronous by nature. This makes it ideal for building real-time applications with reduced latency bottlenecks.</p>
<p><strong>Loose Coupling of Components:</strong> The components in a publish/subscribe model are loosely coupled. This means that they are not tied together and can freely interact by triggering and responding to events.</p>
<p><strong>Highly Scalable:</strong> There is no limit to the number of subscribers a publisher can publish events to. Also, there’s no limit to the number of publishers subscribers can subscribe to.</p>
<p><strong>Independent of Language and Protocol:</strong> The Pub/Sub model can be easily integrated into any tech stack because it is language-agnostic. Also, it often supports a wide range of environments and platforms making it cross-platform compatible.</p>
<p><strong>Load Balancing:</strong> In cases where multiple subscribers subscribe to a particular event, the pub/sub model can distribute the events evenly among the subscribers, providing load-balancing capabilities out of the box.</p>
<h3 id="heading-limitations-of-the-publishsubscribe-pattern">Limitations of the Publish/Subscribe pattern</h3>
<p><strong>Complexity in Implementation:</strong> Setting up a Pub/Sub system can be more complex than simpler communication models like the request-response pattern. You need to configure and manage message brokers, channels, and subscriptions, which can add overhead to your system.</p>
<p><strong>Message Duplication:</strong> Depending on the configuration and network issues, messages can be duplicated. Subscribers might receive the same message more than once, which can lead to redundancy and extra processing.</p>
<p><strong>Scalability Challenges:</strong> While Pub/Sub is highly scalable, managing extremely high volumes of messages and subscribers can become complex. You might need to consider how to distribute messages efficiently and handle massive numbers of subscribers.</p>
<p><strong>Complex Error Handling:</strong> Dealing with errors in a Pub/Sub system can be challenging. Handling situations like message delivery failures or subscriber errors requires careful consideration and design.</p>
<h3 id="heading-when-should-you-use-it">When should you use it?</h3>
<ul>
<li>In building features that require real-time and low latency responsiveness for the end-users, for example live chat or gaming applications for multiple players.</li>
<li>In event notification systems</li>
<li>In building distributed systems that rely on logging and caching</li>
</ul>
<p>Here’s a code snippet showing a simple pub/sub implementation using the npm package <strong><code>pubsub-js</code>.</strong></p>
<p>Here are the contents of the <code>pubsub.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> PubSub = <span class="hljs-built_in">require</span>(<span class="hljs-string">"pubsub-js"</span>);

<span class="hljs-comment">/*
create  a topic of choice.
Any subscriber that subscribes to this topic
receives the published messages
*/</span>
<span class="hljs-keyword">const</span> TOPIC = <span class="hljs-string">"chat"</span>;

<span class="hljs-comment">//a function to publish a messgae to subscribers</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">publishMessageToSubscribers</span>(<span class="hljs-params">message</span>) </span>{
 PubSub.publish(TOPIC, message);
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message Published: <span class="hljs-subst">${message}</span>`</span>);
}

<span class="hljs-keyword">let</span> subscriber1 = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">msg, data</span>) </span>{
 <span class="hljs-built_in">console</span>.log(msg, data);
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"subscriber1 received: "</span>, data);
};

<span class="hljs-keyword">let</span> subscriber2 = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">msg, data</span>) </span>{
 <span class="hljs-built_in">console</span>.log(msg, data);
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"subscriber2 received: "</span>, data);
};

<span class="hljs-comment">// Subscriber1 subscribes to the topic</span>
PubSub.subscribe(TOPIC, subscriber1);

<span class="hljs-comment">//subscriber2 subscribes to topic</span>
PubSub.subscribe(TOPIC, subscriber2);

publishMessageToSubscribers(<span class="hljs-string">"Hello subscriber!"</span>);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Subscriber 1 is listening...."</span>);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Subscriber 2 is listening...."</span>);
</code></pre>
<p>Here's the output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot--180-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-short-polling-pattern">The Short Polling Pattern</h2>
<p>Short polling is another communication pattern that facilitates data exchange between client and server. It uses the <strong>pull-based</strong> communication mechanism (which is basically the client pulling data from the backend) to continuously poll the server for new updates.</p>
<h3 id="heading-how-does-short-polling-work">How does Short Polling work?</h3>
<p>Imagine you’re waiting for a message from a friend, and you don’t want to miss it. What do you do? You keep asking, “Got a message for me yet?”</p>
<p>So, the client makes a request to the server at regular (fixed) intervals (say every x unit of time) to check for new data or updates. The server sends back a response and if there’s new available data or an update, the server includes the data in the response.</p>
<p>Here’s what the client-server communication would look like:</p>
<ul>
<li>Client: “Hey, server, any new messages?”</li>
<li>Server: “Nah, nothing yet.”</li>
<li>Client: “Alright, I’ll check back later.”</li>
<li>[Some time passes…]</li>
<li>Client: “Hey, server, any new messages?”</li>
<li>Server: “Bingo! Here they are!”</li>
</ul>
<p>Although polling has some similarities with the request-response model we discussed earlier, a key difference between them is <strong>timing</strong>. </p>
<p>While polling occurs at regular, predefined intervals regardless of whether updates are available, the request-response model allows clients to request data or actions on-demand when needed, reducing unnecessary communication.</p>
<h3 id="heading-benefits-of-polling">Benefits of Polling</h3>
<p><strong>Simplicity:</strong> Polling is easy to understand and implement and it’s completely stateless between the client and server. This makes it perfect for scenarios where the complexities need to be minimized.</p>
<p><strong>Compatibility:</strong> It can be used with a wide range of technologies and protocols which makes it highly compatible with a number of platforms and environments.</p>
<p>Some example use cases of polling pattern includes simple dashboards, weather apps that require periodic updates, resource monitoring, or in cases where you’re considering cross-platform compatibility.</p>
<h3 id="heading-limitations-of-polling">Limitations of Polling</h3>
<p><strong>Latency:</strong> Polling introduces latency, as clients must wait for predefined intervals before receiving updates. This can lead to delays in accessing real-time data or receiving notifications.</p>
<p><strong>Inefficiency:</strong> Constantly polling the server for updates can be inefficient and can result in unnecessary network and server overhead.</p>
<p><strong>Scaling:</strong> Handling a large number of simultaneous clients using polling can be resource-intensive for the server. It may require significant server resources to manage numerous concurrent polling requests.</p>
<p>Here's a code snippet to illustrate short polling. Here, the client sends a periodic request(polls ) to the server to check for upload progress.</p>
<p>The <code>app.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);

<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">//create a dictionary to store the upload progress</span>
<span class="hljs-keyword">const</span> uploadStatus = {};

<span class="hljs-comment">//simulate upload of file</span>
app.post(<span class="hljs-string">"/upload"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
 <span class="hljs-comment">//create a unique request id for incoming request</span>
 <span class="hljs-keyword">const</span> requestId = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000000</span>);
 uploadStatus[requestId] = <span class="hljs-number">0</span>;

 simulateUploadProgress(requestId);

 res.json({ requestId });
});

<span class="hljs-comment">//endpoint to check upload progress</span>
app.get(<span class="hljs-string">"/status/:requestId"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> requestId = <span class="hljs-built_in">parseInt</span>(req.params.requestId);

 <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">isNaN</span>(requestId) &amp;&amp; uploadStatus[requestId] !== <span class="hljs-literal">undefined</span>) {
  <span class="hljs-keyword">if</span> (uploadStatus[requestId] === <span class="hljs-number">100</span>) {
   <span class="hljs-comment">//upload completed</span>
   res.json({ <span class="hljs-attr">progress</span>: <span class="hljs-number">100</span>, <span class="hljs-attr">message</span>: <span class="hljs-string">"UPLOAD COMPLETED!"</span> });
  } <span class="hljs-keyword">else</span> {
   <span class="hljs-comment">// upload still in progress</span>
   res.json({ <span class="hljs-attr">progress</span>: uploadStatus[requestId] });
  }
 } <span class="hljs-keyword">else</span> {
  res.status(<span class="hljs-number">404</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Request ID not found"</span> });
 }
});

<span class="hljs-comment">//update upload progress by 10% every 5 secs</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">simulateUploadProgress</span>(<span class="hljs-params">requestId</span>) </span>{
 <span class="hljs-keyword">if</span> (uploadStatus[requestId] &lt; <span class="hljs-number">100</span>) {
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
   uploadStatus[requestId] += <span class="hljs-number">10</span>;
   simulateUploadProgress(requestId);
  }, <span class="hljs-number">5000</span>);
 }
}
<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">4000</span>;

app.listen(PORT, <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server is running on port <span class="hljs-subst">${PORT}</span>`</span>);
});
</code></pre>
<p>Here's the output in the terminal</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot--189--1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-the-long-polling-pattern">The Long Polling Pattern</h2>
<p>Long polling is like polling but uses a <strong>push-based</strong> communication mechanism. In long polling, instead of the client asking the server, “Any updates?” all the time, it says, “Let me know when something’s up.”</p>
<h3 id="heading-heres-how-long-polling-works">Here’s how Long Polling works:</h3>
<p>The client pings the server, just like in regular polling, but this time, the server doesn’t immediately answer. It holds the connection open, like keeping a phone line on hold. When there’s something to share, it responds. It’s like the server’s saying, “Hey, I’ll call you when I have news.”</p>
<p>It is used in web applications to achieve real-time or near-real-time updates between a client and a server.</p>
<h3 id="heading-benefits-of-the-long-polling-pattern">Benefits of the Long Polling Pattern</h3>
<p><strong>Low Latency:</strong> Long polling provides low latency when compared to traditional polling as data is immediately sent back to clients as soon as they are available.</p>
<p><strong>Real-Time Updates:</strong> With the long polling technique, applications can achieve real-time updates without the need for constantly polling the server.</p>
<h3 id="heading-limitations-of-the-long-polling-pattern">Limitations of the Long Polling Pattern</h3>
<p><strong>Resource Intensive:</strong> Long polling requires keeping many connections open. As a result, it can be resource-consuming on both the server and client side.</p>
<p><strong>Increased Latency:</strong> Although long polling helps cut down on frequent polling, it can still introduce latency when compared to other real-time communication protocols like Web Socket. Clients may experience delays between updates since they have to wait for the server to respond.</p>
<p><strong>Difficult to Scale:</strong> When dealing with a large number of concurrent clients, long polling can strain server resources. As more clients establish long-polling connections, the server may struggle to manage and respond to all these connections efficiently.</p>
<p>Typical use cases of long polling include real-time updates, event-driven applications, and event notification systems.</p>
<p>Here's a code snippet to illustrate the concept of long polling where the client waits for updates from the server.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-keyword">const</span> uploadStatus = {};

app.post(<span class="hljs-string">"/upload"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> requestId = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">1000000</span>);
 uploadStatus[requestId] = <span class="hljs-number">0</span>;

 updateUploadProgress(requestId, uploadStatus[requestId]);

 res.json({ requestId });
});

app.get(<span class="hljs-string">"/status/:requestId"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
 <span class="hljs-keyword">const</span> requestId = <span class="hljs-built_in">parseInt</span>(req.params.requestId);

 <span class="hljs-comment">//simulate long polling (the server will not respond until done)</span>
 <span class="hljs-keyword">while</span> ((<span class="hljs-keyword">await</span> checkUploadComplete(requestId)) === <span class="hljs-literal">false</span>);
 res.end(<span class="hljs-string">"\n\n Upload status: completed "</span> + uploadStatus[requestId]);
});

<span class="hljs-comment">//update progress by 20% after every 5 seconds</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateUploadProgress</span>(<span class="hljs-params">requestId, progress</span>) </span>{
 uploadStatus[requestId] = progress;
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Updated progress to <span class="hljs-subst">${progress}</span>`</span>);
 <span class="hljs-keyword">if</span> (progress === <span class="hljs-number">100</span>) <span class="hljs-keyword">return</span>;
 <span class="hljs-built_in">this</span>.setTimeout(<span class="hljs-function">() =&gt;</span> updateUploadProgress(requestId, progress + <span class="hljs-number">20</span>), <span class="hljs-number">5000</span>);
}

<span class="hljs-comment">//check upload status</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkUploadComplete</span>(<span class="hljs-params">requestId</span>) </span>{
 <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (uploadStatus[requestId] &lt; <span class="hljs-number">100</span>) {
   <span class="hljs-built_in">this</span>.setTimeout(<span class="hljs-function">() =&gt;</span> resolve(<span class="hljs-literal">false</span>), <span class="hljs-number">1000</span>);
  } <span class="hljs-keyword">else</span> {
   resolve(<span class="hljs-literal">true</span>);
  }
 });
}
<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">4000</span>;

app.listen(PORT, <span class="hljs-function">() =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Server is running on port <span class="hljs-subst">${PORT}</span>`</span>);
});
</code></pre>
<p>And here's the output in the terminal.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot--188-.png" alt="Image" width="600" height="400" loading="lazy">
<em>code output</em></p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/QDvSPKZzf1s" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-the-push-pattern">The Push Pattern</h2>
<p>Push is a communication model that is used to deliver real-time updates to connected clients. </p>
<p>In this model, the client opens a connection to the server and awaits messages or updates from the server. Whenever there is a new update or message, the server immediately <strong>pushes</strong> that update to the client without the client explicitly requesting it — as long it is connected.</p>
<p>This model allows for bidirectional communication between the client and server. Web sockets, a popular protocol, uses the push model as its underlying data exchange method.</p>
<p>The Push model provides the most real-time or near real-time end-user experience when compared to other closely related paradigms such as polling and long polling.</p>
<p>To explain how the push pattern works, imagine a chat room with multiple connected users as an example. The client and server conversation will look like this:</p>
<ul>
<li>user1 (client): “Hello…”</li>
<li>Server: “Oh, user1 has a message!” <em>Instantly sends it to everyone else in the room.</em></li>
<li>User2 (client): <em>Gets the message from user1 without doing anything.</em></li>
<li>User3 (client): <em>Also receives the message from user1 — no need to refresh or ask for it.</em></li>
</ul>
<p>In the example above, the push pattern enables real-time communication such that whenever there’s a message from a client in the chat room, it pushes the message to all other connected clients in that room without them having to continuously poll or request updates.</p>
<p>Popular technologies that uses the push pattern are RabbitMQ and WebSocket.</p>
<h3 id="heading-benefits-of-push-pattern">Benefits of Push Pattern</h3>
<p><strong>Real-Time Updates:</strong> The push model allows clients to receive updates from the server as soon as they are available. This is key, especially in applications where real-time updates are crucial.</p>
<p><strong>Reduced Latency:</strong> Since the server pushes updates to the client as soon as they are available, it potentially reduces the latency.</p>
<p><strong>Efficiency:</strong> Because there is no need for continuous polling or frequent client requests, there is efficient use of network resources and reduced server load.</p>
<p>While the push model is widely adopted as the best fit for providing real-time updates, it does have its own disadvantages.</p>
<h3 id="heading-limitations-of-push-pattern">Limitations of Push Pattern</h3>
<p><strong>Scalability:</strong> It can become difficult to scale as the number of connected clients increases. At this point, it becomes resource-intensive, especially on the server side since the server needs to maintain open connections with multiple clients.</p>
<p><strong>Client support:</strong> Some clients might not be able to handle pushed messages as not all client platforms support push technologies. This may lead to compatibility issues and may need some sort of fallback mechanism for unsupported clients.</p>
<p>Some example use cases of the push pattern include chat and messaging apps, notification systems, IoT data streaming, and online gaming, to name a few.</p>
<p>Here’s a simple Node.js code example to illustrate the push pattern using Web Sockets. To run the code, you have to install the <code>ws</code> library using  <code>npm</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//create a server - this server will push updates to the clients at intervals</span>
<span class="hljs-keyword">const</span> WebSocket = <span class="hljs-built_in">require</span>(<span class="hljs-string">"ws"</span>);
<span class="hljs-keyword">const</span> server = <span class="hljs-keyword">new</span> WebSocket.Server({ <span class="hljs-attr">port</span>: <span class="hljs-number">8080</span> });

server.on(<span class="hljs-string">"connection"</span>, <span class="hljs-function">(<span class="hljs-params">client</span>) =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Client connected to server"</span>);

 <span class="hljs-comment">//Simulate client to receive real-time updates from the server every 2 seconds</span>
 <span class="hljs-keyword">const</span> interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> message = <span class="hljs-string">`Message received at: <span class="hljs-subst">${<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().toLocaleTimeString()}</span>`</span>;
  client.send(message);
 }, <span class="hljs-number">2000</span>);

 <span class="hljs-comment">// Handle client disconnection</span>
 client.on(<span class="hljs-string">"close"</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">clearInterval</span>(interval);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Client disconnected"</span>);
 });
});

<span class="hljs-comment">// Client (listens for updates from server)</span>
<span class="hljs-keyword">const</span> clientSocket = <span class="hljs-keyword">new</span> WebSocket(<span class="hljs-string">"ws://localhost:8080"</span>);

clientSocket.onmessage = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message from server: "<span class="hljs-subst">${event.data}</span>"`</span>);
};
</code></pre>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this tutorial, we explored five key communication design patterns: Request-Response, Publish/Subscribe, Short Polling, Long Polling, and Push. </p>
<p>Each pattern has its unique strengths and limitations which makes them suitable for various use cases. </p>
<p>Depending on your application’s goal, understanding these patterns will help you design efficient backend systems.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
