New APINew API
User GuideInstallationAPI ReferenceAI ApplicationsSkillsHelp & SupportBusiness Cooperation

Cluster Deployment

This document provides detailed configuration steps and best practices for New API cluster deployment, helping you build a highly available, load-balanced distributed system.

Prerequisites

  • Multiple servers (at least two, master-slave architecture)
  • Docker and Docker Compose installed
  • Shared PostgreSQL database (recommended; every application node must access the same database)
  • Optional Redis service (shared by all nodes or deployed independently per node)
  • Optional: Load balancer (e.g., Nginx, HAProxy, or cloud provider's load balancing service)

Cluster Architecture Overview

The New API cluster adopts a master-slave architecture design:

  1. Master Node: Responsible for handling all write operations and some read operations
  2. Slave Nodes: Primarily responsible for handling read operations, improving overall system throughput

Cluster Architecture

The diagram shows a shared-Redis example only. Independent Redis per node and no-Redis deployments are also supported, with the semantics described below.

Key Cluster Deployment Configurations

The key to cluster deployment is that all nodes must:

  1. Share the same database: All nodes access the same PostgreSQL database
  2. Choose a Redis topology: Share Redis, use independent Redis per node, or run without Redis
  3. Use the correct secrets: SESSION_SECRET must be identical on every node; nodes that share Redis must also use the same effective CRYPTO_SECRET
  4. Correctly configure node type: Master node as master, slave nodes as slave

Deployment Steps

Step One: Prepare the Shared Database and Choose a Redis Topology

First, prepare a PostgreSQL database that every application node can access. Prefer one of these options:

  • A managed PostgreSQL service provided by a cloud provider
  • A separately deployed highly available PostgreSQL service
  • PostgreSQL running on an independent server

Common PostgreSQL production architectures include:

ArchitectureComponentsHow it worksApplication configuration
Primary/standby replication1 primary
N standbys
The primary handles reads and writes; standbys replicate continuously and can take overConfigure the primary address as SQL_DSN
High-availability clusterPostgreSQL nodes
Managed endpoint or Patroni + HAProxy
The endpoint routes connections to the current primary and supports automatic failoverConfigure the stable writable endpoint as SQL_DSN

Important Note

In every architecture, SQL_DSN should point to one stable, writable PostgreSQL endpoint. MySQL remains supported, but it is no longer the preferred cluster example.

Ensure these services are accessible by all nodes and have sufficient performance and reliability.

Redis does not replace the shared database. Choose a topology according to your deployment needs:

Redis topologySession-state propagationRate-limit semantics
Shared Redis for all nodesRevocation and version publication normally take effect immediatelyRedis rate-limit quotas are shared across nodes
Independent Redis per nodeFalls back to the shared database and converges within the effective SYNC_FREQUENCY; a newly rotated Access JWT may briefly receive 401 responsesEach node counts independently, so the cluster-wide allowance can be up to approximately the per-node threshold multiplied by the node count
No RedisSession validation reads the shared database directlyEach node uses its local in-memory rate limiter

The user_sessions database table remains authoritative in every topology. Session Redis entries expire after the smaller of the Session's remaining lifetime and the effective SYNC_FREQUENCY; reads do not renew this TTL. Delayed active-cache fills retain only the unused portion of their original database-observation window, so they cannot start a fresh full cache period after a revocation tombstone expires.

Database-backed active-Session limits and Session issuance-window counts are always shared across all nodes. SYNC_FREQUENCY defaults to 60 seconds. Larger values increase the stale window with independent Redis, while smaller values cause more database lookups for each active Session on each node.

Step Two: Configure Master Node

Create a docker-compose.yml file on the master node server:

services:
  new-api-master:
    image: calciumion/new-api:latest
    container_name: new-api-master
    restart: always
    ports:
      - '3000:3000'
    environment:
      - SQL_DSN=postgresql://newapi:password@your-db-host:5432/new-api
      - REDIS_CONN_STRING=redis://default:password@your-redis-host:6379
      - SESSION_SECRET=your_unique_session_secret
      - CRYPTO_SECRET=your_unique_crypto_secret
      - TZ=Asia/Shanghai
      # Optional configuration
      - SYNC_FREQUENCY=60 # Cache synchronization frequency, in seconds
      # - FRONTEND_BASE_URL=https://<your-newapi-domain> # Frontend base URL for email notifications and other functions
    volumes:
      - ./data:/data
      - ./logs:/app/logs

Security Tip

Please replace the example values in the above configuration with strong passwords and randomly generated key strings.

Start the master node:

docker compose up -d

Step Three: Configure Slave Nodes

Create a docker-compose.yml file on each slave node server:

services:
  new-api-slave:
    image: calciumion/new-api:latest
    container_name: new-api-slave
    restart: always
    ports:
      - '3000:3000' # May use the same port as the master because the nodes are on different servers
    environment:
      - SQL_DSN=postgresql://newapi:password@your-db-host:5432/new-api # Must match the master
      - REDIS_CONN_STRING=redis://default:password@your-slave-redis-host:6379 # May match the master or point to this node's independent Redis
      - SESSION_SECRET=your_unique_session_secret # Must match the master
      - CRYPTO_SECRET=your_unique_crypto_secret # Must match the master when Redis is shared
      - NODE_TYPE=slave # Identifies this as a slave node
      - SYNC_FREQUENCY=60 # Cache synchronization frequency, in seconds
      - TZ=Asia/Shanghai
      # Optional configuration
      # - FRONTEND_BASE_URL=https://<your-newapi-domain> # Must match the master
    volumes:
      - ./data:/data
      - ./logs:/app/logs

Start the slave node:

docker compose up -d

Repeat this step for each slave node server.

The example above shows independent Redis instances. To share Redis, use the same REDIS_CONN_STRING on every node. To run without Redis, remove that environment variable. In every topology, SQL_DSN must point to the same database and SESSION_SECRET must be identical on every node.

Step Four: Configure Load Balancer

To achieve balanced traffic distribution, you need to set up a load balancer. Below is a configuration example using Nginx as a load balancer:

upstream new_api_cluster {
    server master-node-ip:3000 weight=3;
    server slave-node1-ip:3000 weight=5;
    server slave-node2-ip:3000 weight=5;
    # Add more slave nodes as needed
}

server {
    listen 80;
    server_name <your-newapi-domain>;

    location / {
        proxy_pass http://new_api_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

This configuration sets the master node weight to 3 and slave node weights to 5, meaning slave nodes will handle more requests. You can adjust these weights according to your actual needs.

Advanced Configuration Options

Data Synchronization Settings

Data synchronization between cluster nodes depends on the following environment variables:

Environment VariableDescriptionRecommended Value
SYNC_FREQUENCYCache synchronization frequency and maximum Session-cache stale window with independent Redis (seconds)60
BATCH_UPDATE_ENABLEDEnable batch updatestrue
BATCH_UPDATE_INTERVALBatch update interval (seconds)5

Redis High Availability Configuration

New API connects through one Redis-compatible endpoint in REDIS_CONN_STRING; it does not natively parse Redis Cluster or Sentinel node lists. For Redis high availability, use a managed service or proxy that exposes one compatible endpoint:

environment:
  - REDIS_CONN_STRING=redis://default:your_redis_password@your-redis-endpoint:6379
  - REDIS_POOL_SIZE=10

Session Security Configuration

Every node must use the same Session secret. Nodes sharing one Redis must also use the same effective cache-key HMAC secret:

environment:
  - SESSION_SECRET=your_unique_session_secret # Must be the same on every node
  - CRYPTO_SECRET=your_unique_crypto_secret # Must match on nodes sharing Redis

Monitoring and Maintenance

Health Checks

Configure regular health checks to monitor node status:

healthcheck:
  test:
    [
      'CMD-SHELL',
      "wget -q -O - http://localhost:3000/api/status | grep -o '\"success\":\\s*true' | awk -F: '{print $$2}'",
    ]
  interval: 30s
  timeout: 10s
  retries: 3

Log Management

For large-scale clusters, a centralized log management system is recommended:

environment:
  - LOG_SQL_DSN=postgresql://newapi:password@log-db-host:5432/new_api_logs # Separate log database

Scaling Guide

As your business grows, you may need to expand your cluster size. The scaling steps are as follows:

  1. Prepare new servers: Install Docker and Docker Compose
  2. Configure slave nodes: Configure new slave nodes according to the instructions in "Step Three: Configure Slave Nodes"
  3. Update load balancer configuration: Add the new nodes to the load balancer configuration
  4. Test new nodes: Ensure the new nodes are working correctly and participating in load balancing

Best Practices

  1. Regularly back up the database: Even in a cluster environment, the database should be backed up regularly
  2. Monitor resource usage: Closely monitor CPU, memory, and disk usage
  3. Adopt a rolling update strategy: When updating, update slave nodes first, and then update the master node after confirming stability
  4. Configure an alerting system: Monitor node status and promptly notify administrators when issues occur
  5. Geographically distributed deployment: If possible, deploy nodes in different geographical locations to improve availability

Troubleshooting

Nodes unable to synchronize data

  • Verify that every node's SQL_DSN points to the same database
  • Confirm that SESSION_SECRET is identical on every node
  • With shared Redis, check the Redis connection and confirm that the effective CRYPTO_SECRET matches
  • With independent Redis, confirm that SYNC_FREQUENCY provides an acceptable cache-convergence window

Load Imbalance

  • Check load balancer configuration and weight settings
  • Monitor resource usage of each node to ensure no node is overloaded
  • May need to adjust node weights or add more nodes

Session Loss Issues

  • Ensure all nodes use the same SESSION_SECRET and shared database
  • With shared Redis, verify that Redis is correctly configured and accessible
  • With independent Redis, a brief 401 after version rotation should recover within the effective SYNC_FREQUENCY; for persistent failures, check database connectivity
  • Check if the client is handling cookies correctly

How is this guide?

Last updated on