Skip to main content

Microservices Architecture

FluxKit wires can be deployed as independent microservices or combined in a single process. This guide shows both approaches.

Monolith (Single Process)

The simplest approach. All wires run in one Node.js process:

import { FluxKit } from "@fluxkitdev/core";
import { auth } from "@fluxkitdev/auth";
import { messaging } from "@fluxkitdev/messaging";
import { store } from "@fluxkitdev/store";
import { pay } from "@fluxkitdev/pay";
import { onchain } from "@fluxkitdev/onchain";

const app = new FluxKit({
wires: [auth(), messaging(), store(), pay(), onchain()],
database: { uri: process.env.MONGODB_URI },
});

await app.start({ port: 3000 });

Best for: Small to medium applications, prototypes, and teams that prefer simplicity.

Microservices (Separate Processes)

Each wire runs in its own process with its own port. They share the same MongoDB database.

Auth Service

// services/auth/src/index.ts
import { FluxKit } from "@fluxkitdev/core";
import { auth } from "@fluxkitdev/auth";

const app = new FluxKit({
wires: [auth()],
database: { uri: process.env.MONGODB_URI },
});

await app.start({ port: 3001 });

Messaging Service

// services/messaging/src/index.ts
import { FluxKit } from "@fluxkitdev/core";
import { messaging } from "@fluxkitdev/messaging";

const app = new FluxKit({
wires: [messaging()],
database: { uri: process.env.MONGODB_URI },
});

await app.start({ port: 3002 });

Store Service

// services/store/src/index.ts
import { FluxKit } from "@fluxkitdev/core";
import { store } from "@fluxkitdev/store";

const app = new FluxKit({
wires: [store()],
database: { uri: process.env.MONGODB_URI },
});

await app.start({ port: 3003 });

Docker Compose

Run all services with Docker:

# docker-compose.yml
version: "3.8"

services:
mongodb:
image: mongo:7
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db

auth:
build:
context: ./services/auth
ports:
- "3001:3001"
environment:
- MONGODB_URI=mongodb://mongodb:27017/myapp
- JWT_SECRET=${JWT_SECRET}
- PORT=3001
depends_on:
- mongodb

messaging:
build:
context: ./services/messaging
ports:
- "3002:3002"
environment:
- MONGODB_URI=mongodb://mongodb:27017/myapp
- SMTP_HOST=${SMTP_HOST}
- SMTP_PORT=${SMTP_PORT}
- SMTP_USER=${SMTP_USER}
- SMTP_PASS=${SMTP_PASS}
- PORT=3002
depends_on:
- mongodb

store:
build:
context: ./services/store
ports:
- "3003:3003"
environment:
- MONGODB_URI=mongodb://mongodb:27017/myapp
- S3_BUCKET=${S3_BUCKET}
- S3_REGION=${S3_REGION}
- S3_ACCESS_KEY=${S3_ACCESS_KEY}
- S3_SECRET_KEY=${S3_SECRET_KEY}
- PORT=3003
depends_on:
- mongodb

frontend:
build:
context: ./frontend
ports:
- "80:80"

volumes:
mongo-data:

Reverse Proxy (nginx)

Route requests to the correct service:

# nginx.conf
upstream auth_service {
server auth:3001;
}
upstream messaging_service {
server messaging:3002;
}
upstream store_service {
server store:3003;
}

server {
listen 80;

location /auth/ {
proxy_pass http://auth_service;
}

location /messaging/ {
proxy_pass http://messaging_service;
}

location /store/ {
proxy_pass http://store_service;
}

location /health {
proxy_pass http://auth_service;
}

location / {
root /usr/share/nginx/html;
try_files $uri /index.html;
}
}

Shared Dockerfile

Each service uses the same Dockerfile pattern:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY dist/ ./dist/
EXPOSE ${PORT:-3000}
CMD ["node", "dist/index.js"]

Service-to-Service Communication

If services need to communicate with each other, use the HTTP client from the core wire:

// In the auth service, send a welcome email via the messaging service
import { FluxKit } from "@fluxkitdev/core";

const app = new FluxKit({ ... });

app.http.post("/auth/register", {
handler: async (req, res) => {
const user = await app.auth.createUser(req.body);

// Call the messaging service
await fetch("http://messaging:3002/messaging/email", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${internalToken}`,
},
body: JSON.stringify({
to: user.email,
subject: "Welcome!",
body: "<h1>Welcome to our platform!</h1>",
}),
});

res.status(201).json({ user });
},
});

Hybrid Approach

Group related wires together. This is often the best balance between simplicity and scalability:

Service 1 (User-facing):  auth + store
Service 2 (Background): messaging
Service 3 (Payments): pay + onchain
Service 4 (Frontend): @fluxkitdev/ui (React)
// services/user/src/index.ts
const app = new FluxKit({
wires: [auth(), store()],
database: { uri: process.env.MONGODB_URI },
});
await app.start({ port: 3001 });

Scaling

Each service can be scaled independently:

docker compose up --scale messaging=3 --scale store=2

Since all services share the same MongoDB database, there is no need for data synchronization between services.