Session Management
The DeployStack Gateway implements a robust session management system that provides cryptographically secure session handling for persistent SSE connections while ensuring automatic cleanup and resource management.
Architecture Overview
The session management system consists of two primary components working together to provide secure, persistent connections:
- SessionManager: Handles session lifecycle, validation, and SSE stream management
- SSEHandler: Manages Server-Sent Events connections and message routing
Core Components
Cryptographic Security
256-bit entropy session IDs with base64url encoding for maximum security
Lifecycle Management
Automatic session creation, validation, activity tracking, and timeout handling
Connection Validation
Session-bound SSE streams with comprehensive validation and error handling
Automatic Cleanup
Resource cleanup on disconnect, timeout, or error conditions
Session ID Generation
Cryptographic Properties
- Algorithm: Node.js
crypto.randomBytes(32)
- Entropy: 256 bits (32 bytes) of cryptographically secure randomness
- Encoding: Base64url for URL safety and compatibility
- Format:
L8B-xaw3HBZEftyo-JCrHoGWb_iikRZiwGfp9B71-GA
Security Features
- Unpredictability: Cryptographically secure random number generation
- Collision Resistance: 2^256 possible values make collisions virtually impossible
- URL Safety: Base64url encoding ensures compatibility in query parameters
- No Sequential Patterns: Each session ID is completely independent
Validation Process
private validateSessionId(sessionId: string): boolean {
if (!sessionId || typeof sessionId !== 'string') return false;
if (sessionId.length < 32) return false;
if (!/^[A-Za-z0-9_-]+$/.test(sessionId)) return false;
return true;
}
Session Lifecycle
1. Creation Phase
Trigger: SSE connection establishment via GET /sse
Process:
- Generate cryptographically secure session ID
- Create session object with metadata
- Associate with SSE stream
- Schedule automatic cleanup timer
- Send endpoint event to client
Session Object:
interface SessionInfo {
id: string;
createdAt: number;
lastActivity: number;
sseStream: ServerResponse;
clientInfo?: { name: string; version: string };
mcpInitialized: boolean;
requestCount: number;
errorCount: number;
}
2. Active Phase
Duration: Until timeout or disconnect
Activities:
- Activity Tracking: Updated on every JSON-RPC request
- Request Counting: Incremented for each message processed
- Error Tracking: Incremented on processing failures
- Client Info Storage: MCP client metadata stored during initialization
3. Cleanup Phase
Triggers:
- Client disconnect (
close
event) - Connection error (
error
event) - Stream finish (
finish
event) - 30-minute inactivity timeout
Process:
- Close SSE stream if still open
- Remove session from active sessions map
- Log cleanup completion
- Free associated resources
Connection Management
SSE Stream Handling
The session manager maintains direct references to SSE streams for efficient message delivery:
sendToSession(sessionId: string, event: { id?: string; event?: string; data: string }): boolean {
const session = this.sessions.get(sessionId);
if (!session || session.sseStream.destroyed) {
return false;
}
try {
let sseData = '';
if (event.id) sseData += `id: ${event.id}\n`;
if (event.event) sseData += `event: ${event.event}\n`;
sseData += `data: ${event.data}\n\n`;
session.sseStream.write(sseData);
return true;
} catch (error) {
this.cleanupSession(sessionId);
return false;
}
}
Connection State Tracking
- Stream Health: Monitors SSE stream status and handles disconnects
- Activity Monitoring: Tracks last activity timestamp for timeout detection
- Error Handling: Graceful handling of connection failures and cleanup
- Resource Management: Prevents memory leaks through automatic cleanup
Security Considerations
Session Security
- Unpredictable IDs: Impossible to guess or enumerate session IDs
- Time-Limited: Automatic expiration prevents indefinite access
- Connection-Bound: Sessions tied to specific SSE connections
- Validation: Comprehensive validation on every request
Timeout Management
- Inactivity Timeout: 30 minutes of inactivity triggers cleanup
- Automatic Scheduling: Cleanup scheduled at session creation
- Activity Extension: Timeout reset on each valid request
- Resource Protection: Prevents accumulation of stale sessions
Error Handling
- Graceful Degradation: Connection errors don't crash the system
- Automatic Recovery: Failed connections cleaned up automatically
- Error Isolation: Session errors don't affect other sessions
- Logging: Comprehensive error logging for debugging
Performance Optimization
Memory Management
- Efficient Storage: Sessions stored in Map for O(1) lookup
- Automatic Cleanup: Prevents memory leaks through timeout handling
- Resource Tracking: Monitors session count and resource usage
- Garbage Collection: Proper cleanup enables efficient garbage collection
Connection Efficiency
- Persistent Connections: SSE streams maintained for duration of session
- Minimal Overhead: Lightweight session objects with essential data only
- Fast Lookup: Session validation and retrieval optimized for speed
- Batch Operations: Efficient handling of multiple concurrent sessions
Monitoring and Debugging
Session Statistics
The session manager provides comprehensive statistics for monitoring:
getStatus() {
return {
activeCount: this.sessions.size,
sessions: Array.from(this.sessions.values()).map(session => ({
id: session.id,
createdAt: session.createdAt,
lastActivity: session.lastActivity,
uptime: Date.now() - session.createdAt,
requestCount: session.requestCount,
errorCount: session.errorCount,
clientInfo: session.clientInfo,
mcpInitialized: session.mcpInitialized
}))
};
}
Logging and Observability
- Session Creation: Logged with session ID for tracking
- Activity Updates: Request and error counts tracked
- Cleanup Events: Cleanup reasons and timing logged
- Error Conditions: Detailed error logging for troubleshooting
Integration Points
SSE Handler Integration
The session manager works closely with the SSE handler:
// Session creation during SSE establishment
const sessionId = this.sessionManager.createSession(reply.raw);
// Message routing through sessions
this.sseHandler.sendMessage(sessionId, response);
// Error handling via sessions
this.sseHandler.sendError(sessionId, errorResponse);
HTTP Proxy Integration
Session validation in the HTTP proxy:
// Session validation on each request
const session = this.sessionManager.getSession(sessionId);
if (!session) {
// Handle invalid session
}
// Activity tracking
this.sessionManager.updateActivity(sessionId);
// Error counting
this.sessionManager.incrementErrorCount(sessionId);
Best Practices
Session Lifecycle
- Immediate Creation: Sessions created immediately on SSE connection
- Activity Tracking: Update activity on every valid request
- Graceful Cleanup: Always clean up resources on session end
- Error Handling: Handle all error conditions gracefully
Security Practices
- Validate Always: Validate session ID on every request
- Time Limits: Enforce reasonable session timeouts
- Resource Limits: Monitor and limit concurrent sessions if needed
- Audit Trail: Log session activities for security monitoring
Performance Practices
- Efficient Lookup: Use Map for O(1) session lookup
- Minimal Data: Store only essential session data
- Cleanup Scheduling: Schedule cleanup to prevent resource leaks
- Error Recovery: Implement robust error recovery mechanisms
The session management system provides a secure, efficient, and robust foundation for persistent SSE connections while maintaining enterprise-grade security and operational requirements.