Architecture Overview
Event Flow
Why Events vs Heartbeat?
DeployStack uses three distinct communication channels: Heartbeat (Every 30 seconds):- Aggregate metrics and system health
- Resource monitoring and capacity planning
- Process counts grouped by team
- Point-in-time occurrences with precise timestamps
- Real-time UI updates and user notifications
- Audit trails for compliance
- Backend-initiated tasks
- Configuration updates and process management
Backend Implementation
Directory Structure
Convention-Based Handler Discovery
The dispatcher automatically discovers and registers handlers from thehandlerModules array in index.ts:
- EVENT_TYPE: String constant identifying the event
- SCHEMA: JSON Schema for AJV validation
- handle(): Async function that updates business tables
Handler Interface
All event handlers must implement this interface:Event Processing
Batch Endpoint
Route:POST /api/satellites/{satelliteId}/events
Authentication: Satellite API key (Bearer token via requireSatelliteAuth() middleware)
Request Schema (uses snake_case for all fields):
Batch Processing Strategy
The dispatcher processes batched events with isolated error handling:- Validate request structure (events array present)
- Validate batch size (1-100 events)
- Process each event individually:
- Check event type exists in registry
- Validate event data against handler schema using AJV
- Parse and validate timestamp
- Call handler.handle() for valid events
- Track successful and failed events
- Return aggregated results
Partial Success Handling
When some events fail validation, the endpoint returns partial success:Implemented Event Types
MCP Server Lifecycle
mcp.server.started
UpdatessatelliteProcesses table when server successfully spawns.
Business Logic: Sets status=‘running’, records start time and process PID.
Required Fields (snake_case): process_id, server_id, server_slug, team_id, transport, tool_count, spawn_duration_ms
Optional Fields: pid (OS process ID)
mcp.server.crashed
UpdatessatelliteProcesses table when server exits unexpectedly.
Business Logic: Sets status=‘failed’, logs error details and exit code.
Required Fields (snake_case): process_id, server_id, server_slug, team_id, exit_code, signal, uptime_seconds, crash_count, will_restart
Optional Fields: None (all fields required for proper crash tracking)
Tool Execution
mcp.tool.executed
Inserts record intosatelliteUsageLogs for analytics and audit trails.
Business Logic: Logs tool execution with metrics, user context, and performance data.
Required Fields (snake_case): tool_name, server_id, team_id, duration_ms, success
Optional Fields: error_message (string, only present when success=false)
Creating New Event Handlers
Handler Template
CRITICAL: All event data fields MUST use snake_case naming convention to match satellite event emission and backend API standards. Create a new file inservices/backend/src/events/satellite/:
Registration Steps
- Create handler file in
services/backend/src/events/satellite/ - Export
EVENT_TYPE,SCHEMA, andhandle()function - Add import to
handlerModulesarray inindex.ts:
- Handler is automatically registered and ready to process events
Schema Validation
AJV Configuration
The dispatcher uses AJV with specific configuration for compatibility:Validation Process
For each event:- Compile handler SCHEMA with AJV
- Validate event.data against compiled schema
- Log validation errors with instance path details
- Skip invalid events (don’t fail entire batch)
Schema Best Practices
- Use
minLength: 1for required string fields - Include descriptive
descriptionfields for documentation - Set
additionalProperties: trueto allow future extensibility - Use
requiredarray for mandatory fields - Leverage AJV formats:
email,date-time,uri,uuid
Database Integration
Event-to-Table Mapping
Events route to existing business tables based on their purpose:| Event Type | Business Table | Action |
|---|---|---|
mcp.server.started | satelliteProcesses | Update status=‘running’, set start time |
mcp.server.crashed | satelliteProcesses | Update status=‘failed’, log error details |
mcp.tool.executed | satelliteUsageLogs | Insert usage record with metrics |
Transaction Strategy
Each event is processed in a separate database transaction:- Failed events don’t rollback other events
- Maintains data consistency per event
- Isolated error handling prevents cascade failures
Performance Considerations
Batch Processing Efficiency
- Target: < 100ms per 100-event batch
- Isolation: Each event in separate transaction
- Logging: Structured logging with batch metrics
- Monitoring: Track processing duration and success rates
Database Performance
- Updates use indexed lookups (processId, satelliteId)
- Inserts optimized for high-volume logging
- No generic JSON storage overhead
- Leverages existing optimized table schemas
Memory Usage
- Batch size limited to 100 events (backend validation)
- Event processing is sequential (simple implementation)
- No long-lived memory allocations
- Efficient JSON parsing with TypeScript interfaces
Error Handling
Invalid Event Type
Response: Partial success with failure details Logging: Warn level with event type Action: Skip event, continue batch processingSchema Validation Failure
Response: Partial success with validation errors Logging: Warn level with instance path details Action: Skip event, log validation errorsHandler Execution Error
Response: Partial success with error message Logging: Error level with stack trace Action: Catch error, track failure, continue batchDatabase Transaction Failure
Response: Partial success with database error Logging: Error level with query details Action: Rollback transaction, track failure, continue batchTesting
Unit Testing
Test individual event handlers in isolation:Integration Testing
Test full endpoint with satellite authentication:Batch Processing Tests
- Single event batch (1 event)
- Normal batch (50 events)
- Maximum batch (100 events)
- Oversized batch (> 100 events, should reject)
- Mixed success/failure batch
- Unknown event type handling
- Invalid timestamp handling
- Schema validation failures
Monitoring and Debugging
Structured Logging
All event operations are logged with structured data:Debug Queries
Check registered event types:Best Practices
Event Handler Design
DO:- Update existing business tables with structured data
- Use TypeScript interfaces for type safety
- Include comprehensive field descriptions in schemas
- Log important state changes
- Handle optional fields gracefully
- Store raw JSON in generic events tables
- Assume all optional fields are present
- Skip error handling in database operations
- Use blocking operations (keep handlers async)
- Duplicate business logic across handlers
Schema Design
DO:- Use descriptive field names matching domain concepts
- Include
descriptionfor documentation - Set appropriate
minLengthand format constraints - Use
additionalProperties: truefor extensibility - Mark truly required fields in
requiredarray
- Over-constrain with excessive validation
- Use generic field names like
dataorinfo - Forget to set
as conston schema objects - Validate business logic in schemas (do that in handlers)
- Create schemas with circular references
Database Operations
DO:- Use parameterized queries via Drizzle ORM
- Use PostgreSQL-specific features when needed
- Include timestamps for all state changes
- Use transactions for multi-step operations
- Index frequently queried fields
- Concatenate SQL strings manually
- Assume specific driver properties exist
- Skip error handling for database operations
- Create N+1 query patterns
- Store large BLOBs in event data
Future Enhancements
Planned Event Types
- Client Connections:
mcp.client.connected,mcp.client.disconnected - Tool Discovery:
mcp.tools.discovered,mcp.tools.updated - Configuration:
config.refreshed,config.error - Satellite Lifecycle:
satellite.registered,satellite.deregistered - Process Management:
mcp.server.restarted,mcp.server.permanently_failed
Performance Optimizations
- Batch database insertions for high-volume events
- Async event processing with job queue
- Event sampling for high-frequency events
- Compression for large event payloads
Analytics Features
- Real-time event aggregation
- Custom alert rules based on events
- Event replay for debugging
- Historical event analysis dashboards
Related Documentation
- Satellite Event System - Satellite-side event emission
- Satellite Communication - Full satellite communication architecture
- API Documentation - OpenAPI specification generation
- Database Management - Schema and migrations

