cd..blog

Scaling TypeScript Microservices: Moleculer, Fly.io, Auth, & Debugging

const published = "Jan 17, 2026, 10:37 PM";const readTime = 6 min;
typescriptmoleculerfly.iomicroservicesauthentication
Learn to integrate Moleculer microservices, secure them with JWT authentication, test with Jest, debug efficiently, and deploy seamlessly on Fly.io using TypeScript.

Scaling TypeScript Microservices: Moleculer, Fly.io, Auth, & Debugging

Building robust, scalable web applications in 2026 demands a sophisticated approach to architecture, security, and deployment. This post demonstrates how to integrate Moleculer microservices, secure them with comprehensive authentication, ensure quality through testing and debugging, and deploy globally with Fly.io – all powered by TypeScript.

Moleculer: Building Microservices

Moleculer is a fast, modern, and powerful microservices framework for Node.js, offering features like service discovery, load balancing, and fault tolerance out-of-the-box. We use it to structure our application into small, independent services, enhancing maintainability and scalability. Moleculer Documentation

Let's define a simple users service:

// services/users.service.ts
import { Service, ServiceBroker, Context } from "moleculer";

interface UserProfile { id: string; username: string; email: string; roles: string[]; }

export default class UsersService extends Service {
  public constructor(broker: ServiceBroker) {
    super(broker);
    this.parseServiceSchema({
      name: "users",
      actions: {
        profile: {
          // Only authenticated users can access their profile
          auth: true,
          handler(ctx: Context<{ userId: string }>): UserProfile {
            // In a real app, fetch from DB
            if (ctx.meta.user && ctx.meta.user.id === ctx.params.userId) {
              return { id: ctx.params.userId, username: "testuser", email: "test@example.com", roles: ["user"] };
            }
            throw new Error("Unauthorized access or user not found.");
          },
        },
      },
    });
  }
}

Secure Access: Authentication & Authorization

Authentication verifies user identity, while authorization determines what actions they can perform. We'll implement a JWT-based authentication middleware in Moleculer to protect our service actions. This middleware decodes the JWT and attaches user information to the context.meta object. JSON Web Tokens (JWT)

// middlewares/auth.middleware.ts
import { ServiceBroker, Context, Middleware } from "moleculer";
import jwt from "jsonwebtoken";

const SECRET = process.env.JWT_SECRET || "super-secret-jwt-key";

export const AuthMiddleware = (broker: ServiceBroker): Middleware => {
  return {
    localAction(handler, action) {
      return async function(ctx: Context) {
        // Check if action requires authentication
        if (action.auth) {
          const authHeader = ctx.meta.headers?.authorization;
          if (!authHeader || !authHeader.startsWith("Bearer ")) {
            throw new Error("Authentication required.");
          }
          const token = authHeader.split(" ")[1];
          try {
            const decoded = jwt.verify(token, SECRET) as { id: string; roles: string[]; };
            ctx.meta.user = decoded; // Attach user info to context meta
          } catch (err) {
            throw new Error("Invalid or expired token.");
          }
        }
        return handler(ctx);
      };
    },
  };
};

// broker.ts (excerpt)
// const broker = new ServiceBroker({
//   middlewares: [AuthMiddleware(broker)],
//   // ... other configurations
// });

Ensuring Quality: Testing with Jest

Robust testing is crucial for microservices. Jest provides a powerful and flexible testing framework for TypeScript applications. We use it to write unit and integration tests for our Moleculer services, ensuring their logic works as expected. Jest Documentation

// __tests__/users.service.spec.ts
import { ServiceBroker } from "moleculer";
import UsersService from "../services/users.service";
import { AuthMiddleware } from "../middlewares/auth.middleware";
import jwt from "jsonwebtoken";

describe("Users Service", () => {
  let broker: ServiceBroker;
  let validToken: string;

  beforeAll(() => {
    broker = new ServiceBroker({
      nodeID: "test-node",
      logLevel: "warn",
      middlewares: [AuthMiddleware(broker)], // Apply auth middleware for testing
    });
    broker.createService(UsersService);
    validToken = jwt.sign({ id: "user123", roles: ["user"] }, process.env.JWT_SECRET || "super-secret-jwt-key", { expiresIn: "1h" });
    return broker.start();
  });

  afterAll(() => broker.stop());

  it("should fetch user profile for an authenticated user", async () => {
    const profile = await broker.call("users.profile", { userId: "user123" }, {
      meta: { headers: { authorization: `Bearer ${validToken}` } },
    });
    expect(profile).toHaveProperty("username", "testuser");
    expect(profile.id).toBe("user123");
  });

  it("should throw an error for unauthenticated access", async () => {
    await expect(broker.call("users.profile", { userId: "user123" })).rejects.toThrow("Authentication required.");
  });
});

Streamlined Development: Debugging with VS Code

Debugging TypeScript applications in VS Code is highly efficient. By configuring launch.json, developers can set breakpoints, inspect variables, and step through code, significantly speeding up issue resolution. VS Code Debugging

Create a .vscode/launch.json file:

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Moleculer Service",
      "skipFiles": [
        "<node_internals>/**"
      ],
      "program": "${workspaceFolder}/src/app.ts", // Your main Moleculer entry file
      "preLaunchTask": "tsc: build - tsconfig.json", // Ensure TypeScript is compiled
      "outFiles": [
        "${workspaceFolder}/dist/**/*.js"
      ],
      "env": {
        "JWT_SECRET": "super-secret-jwt-key"
      }
    }
  ]
}

Global Deployment: Fly.io Integration

Fly.io offers a global application platform that brings your apps closer to users, reducing latency and improving performance. It's ideal for deploying microservices due to its focus on edge deployment and simplified container orchestration. Fly.io Documentation

First, a Dockerfile to containerize your Moleculer app:

# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY . .
RUN npm run build # Assuming a 'build' script for TypeScript compilation
EXPOSE 3000 # Moleculer API Gateway port
CMD ["npm", "start"]

Then, fly.toml for Fly.io configuration:

# fly.toml
app = "my-moleculer-app"
primary_region = "lhr" # Choose your primary region

[build]
  builder = "heroku/buildpacks:20"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1
  processes = ["app"]

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory = "256mb"

Deploying is as simple as fly launch followed by fly deploy from your project root.

Conclusion

By integrating Moleculer for microservices, JWT for security, Jest for testing, VS Code for debugging, and Fly.io for global deployment, you establish a robust, scalable, and developer-friendly ecosystem. This comprehensive approach ensures your TypeScript applications are performant, secure, and maintainable, ready for the demands of modern web development.