# How to Manage Multiple WhatsApp Sessions Concurrently Using OpenWA

> Learn to manage multiple WhatsApp sessions concurrently with OpenWA. This guide shows how to use its session-centric architecture and APIs for unlimited simultaneous connections.

- Repository: [Yudhi Armyndharis/OpenWA](https://github.com/rmyndharis/OpenWA)
- Tags: how-to-guide
- Published: 2026-05-21

---

**OpenWA enables concurrent WhatsApp automation through a session-centric architecture where each connection runs as an isolated engine instance managed by the SessionService, allowing you to create, monitor, and interact with unlimited sessions simultaneously via REST or WebSocket APIs.**

The rmyndharis/OpenWA repository provides a production-ready Node.js solution for managing multiple WhatsApp sessions concurrently using OpenWA. By isolating each WhatsApp Web connection in its own engine instance while persisting session metadata to PostgreSQL, the framework ensures that operations on one session never interfere with others, making it ideal for multi-tenant applications and high-scale messaging platforms.

## Understanding OpenWA's Concurrent Session Architecture

At the heart of the system is the **SessionService** located in [`src/modules/session/session.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/session/session.service.ts). This service maintains a private in-memory Map that stores live engine instances: `private engines: Map<string, IWhatsAppEngine>`, where each key represents a unique session ID and the value is a fully initialized WhatsApp engine.

The **EngineFactory** in [`src/engine/engine.factory.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/engine/engine.factory.ts) implements a factory pattern to instantiate concrete engine implementations. Currently, it produces `whatsapp-web-js` adapters that implement the **IWhatsAppEngine** interface defined in [`src/engine/interfaces/whatsapp-engine.interface.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/engine/interfaces/whatsapp-engine.interface.ts). This abstraction allows each session to operate with its own browser context, authentication state, and event handlers, ensuring true process isolation at the application layer.

Session persistence is handled via TypeORM, with the `Session` entity in [`src/modules/session/entities/session.entity.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/session/entities/session.entity.ts) storing configuration, status, and metadata in PostgreSQL. This separation between persistent state (database) and runtime state (in-memory Map) enables the system to restore sessions after restarts while maintaining active connection pools only for running sessions.

## Creating and Configuring New Sessions

To add a new concurrent session, you insert a record into the database via the REST API. The `CreateSessionDto` in [`src/modules/session/dto/create-session.dto.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/session/dto/create-session.dto.ts) defines the expected payload, including session-specific reconnection parameters.

```http
POST /sessions
Content-Type: application/json

{
  "name": "store-location-1",
  "config": {
    "maxReconnectAttempts": 8,
    "reconnectBaseDelay": 4000
  }
}

```

Internally, `SessionService.create()` writes the record and emits the `session:created` hook. At this stage, the session exists in the database with status `CREATED`, but no engine instance occupies memory in the `engines` Map.

## Starting Sessions and Initializing Engines

Activation occurs through the start endpoint, which triggers the full lifecycle initialization:

```http
POST /sessions/{sessionId}/start

```

The `SessionService.start()` method creates a `ReconnectState` object for the session, then calls `initializeEngine()` to instantiate a new engine via the **EngineFactory**. The factory injects session-specific configuration—including proxy settings and browser options—into the `whatsapp-web-js` adapter located at [`src/plugins/engines/whatsapp-web-js/index.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/plugins/engines/whatsapp-web-js/index.ts).

Once initialized, the engine generates a QR code for authentication. The service captures this through the `onQRCode` callback and broadcasts it via the **EventsGateway** in [`src/modules/events/events.gateway.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/events/events.gateway.ts), which pushes real-time updates to connected WebSocket clients.

```typescript
import { OpenWAClient } from '@openwa/sdk';

const client = new OpenWAClient({ baseUrl: 'http://localhost:3000' });

await client.sessions.start(sessionId);
const { qrCode, status } = await client.sessions.getQRCode(sessionId);
// Render qrCode (base64 PNG) for user scanning

```

## Routing Messages to Specific Sessions

When sending messages, the system routes requests to the correct engine using the session ID. The `MessageService` resolves the appropriate instance via `this.sessionService.getEngine(sessionId)`, ensuring that "Hello from session A" never routes through session B's connection.

```http
POST /sessions/{sessionId}/messages
Content-Type: application/json

{
  "to": "628123456789",
  "body": "Hello from session 1!"
}

```

```typescript
await client.sessions.messages.send(sessionId, {
  to: '628123456789',
  body: 'Hello from session 1!'
});

```

This isolation extends to all engine operations—including `getGroups`, `getContacts`, and media handling—preventing session data leakage across tenant boundaries.

## Handling Reconnection and Session Resilience

Each concurrent session maintains independent reconnection logic stored in the `reconnectStates` Map within **SessionService**. When a `whatsapp-web-js` engine disconnects, the service evaluates the session's `maxReconnectAttempts` and `reconnectBaseDelay` configuration to execute an exponential backoff strategy.

If reconnection succeeds, the engine re-enters the `READY` state without affecting other sessions. If attempts exhaust, the status updates to `FAILED` and the engine instance is removed from the Map, freeing memory while preserving session history in PostgreSQL.

## Monitoring Session Health and Performance

The service exposes aggregate metrics for observability dashboards. Calling `SessionService.getStats()` returns active counts, memory usage, and status distributions across all sessions.

```http
GET /sessions/stats

```

```typescript
const stats = await client.sessions.getStats();
console.log('Active engines:', stats.active);
console.log('Ready sessions:', stats.ready);
console.log('Memory (MB):', stats.memoryUsage);

```

For real-time monitoring, the **EventsGateway** streams session-level events—`session:qr`, `session:ready`, `message:received`—to frontend clients, while the optional **WebhookService** in [`src/modules/webhook/webhook.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/webhook/webhook.service.ts) forwards these events to external HTTP endpoints per session configuration.

## Graceful Session Termination

To stop a specific session without impacting others:

```http
POST /sessions/{sessionId}/stop

```

```typescript
await client.sessions.stop(sessionId);

```

`SessionService.stop()` cancels pending reconnection timers, calls `engine.destroy()`, removes the entry from the `engines` Map, and updates the database status to `DISCONNECTED`. This clean teardown prevents memory leaks when managing high-churn session pools.

## Summary

- **SessionService** in [`src/modules/session/session.service.ts`](https://github.com/rmyndharis/OpenWA/blob/main/src/modules/session/session.service.ts) orchestrates concurrent sessions using an in-memory Map of `IWhatsAppEngine` instances, ensuring isolation between connections.
- Each session receives its own engine via the **EngineFactory**, allowing independent configuration of proxies, reconnection policies, and browser contexts.
- The REST API provides endpoints for creating (`POST /sessions`), starting (`POST /sessions/:id/start`), messaging (`POST /sessions/:id/messages`), and monitoring (`GET /sessions/stats`) individual sessions.
- Real-time events flow through **EventsGateway** and optionally **WebhookService**, enabling reactive UIs and external integrations per session.
- Reconnection handling is session-specific with exponential backoff, configured via `maxReconnectAttempts` and `reconnectBaseDelay` parameters.

## Frequently Asked Questions

### How many concurrent WhatsApp sessions can OpenWA handle?

The theoretical limit depends on available system memory and CPU, as each session maintains a separate `whatsapp-web-js` engine instance in the `engines` Map. In production deployments, organizations typically run hundreds of concurrent sessions per instance by tuning Node.js memory limits and using appropriate proxy rotation to prevent rate limiting.

### What database does OpenWA use for session persistence?

OpenWA uses PostgreSQL via TypeORM to persist session metadata, configuration, and status history in the `Session` entity. While runtime engine objects live in memory, the database ensures that session records survive application restarts and enable horizontal scaling behind load balancers.

### How does OpenWA isolate sessions to prevent cross-contamination?

Session isolation occurs at the architecture level: the **SessionService** stores each engine as a distinct value in a `Map<string, IWhatsAppEngine>` keyed by session ID. The **EngineFactory** creates separate browser contexts for each session, and the `MessageService` explicitly resolves engines via `getEngine(sessionId)`, ensuring that authentication tokens, message queues, and event handlers never overlap between sessions.

### Can I configure different proxy settings for each concurrent session?

Yes, proxy configuration is passed per-session to the **EngineFactory** during `initializeEngine()`. When creating a session via `POST /sessions`, include proxy details in the config object, and the factory will instantiate the `whatsapp-web-js` adapter with those specific network settings, allowing geographically distributed sessions from a single OpenWA instance.