App Managers
The app manager is the source of truth for application credentials, limits, and webhook configurations. Every WebSocket connection and API request is validated against the app manager.
Drivers
| Driver | Best For | Persistence | External Dependency |
|---|---|---|---|
memory | Development, single-node | None (lost on restart) | None |
mysql | Production with MySQL stack | Full | MySQL 5.7+ |
postgres | Production with PostgreSQL stack | Full | PostgreSQL 12+ |
dynamodb | Serverless / AWS-native | Full | AWS DynamoDB |
scylladb | High-throughput, low-latency | Full | ScyllaDB / Cassandra |
Set the driver:
APP_MANAGER_DRIVER=memory
{ "app_manager": { "driver": "memory" } }
Memory Driver
The default driver. Apps are defined inline in config.json or bootstrapped via environment variables. Data is not persisted - apps are lost on restart.
{
"app_manager": {
"driver": "memory",
"array": {
"apps": [
{
"id": "my-app-id",
"key": "my-app-key",
"secret": "my-app-secret",
"enabled": true,
"enable_client_messages": true,
"max_connections": 100000,
"max_client_events_per_second": 1000
}
]
}
}
}
You can also bootstrap a default app entirely from environment variables:
SOCKUDO_DEFAULT_APP_ID=my-app-id
SOCKUDO_DEFAULT_APP_KEY=my-app-key
SOCKUDO_DEFAULT_APP_SECRET=my-app-secret
SOCKUDO_DEFAULT_APP_ENABLED=true
See Environment Variables for all SOCKUDO_DEFAULT_APP_* options.
MySQL Driver
Stores apps in a MySQL table with automatic schema migrations. Includes built-in query caching.
{
"app_manager": {
"driver": "mysql"
},
"database": {
"mysql": {
"host": "localhost",
"port": 3306,
"username": "sockudo",
"password": "secret",
"database": "sockudo",
"table_name": "applications"
}
}
}
Connection Pooling
MySQL connections are pooled automatically:
| Setting | Default | Description |
|---|---|---|
connection_pool_size | 10 | Pool size (legacy, used if pool_min/max not set) |
pool_min | null | Minimum connections (overrides global) |
pool_max | null | Maximum connections (overrides global) |
You can also set global pool limits:
DATABASE_POOLING_ENABLED=true
DATABASE_POOL_MIN=2
DATABASE_POOL_MAX=10
Query Caching
App lookups are cached in-memory to avoid repeated database queries:
| Setting | Default | Description |
|---|---|---|
cache_ttl | 300 | Cache TTL in seconds |
cache_cleanup_interval | 60 | Cleanup interval in seconds |
cache_max_capacity | 100 | Maximum cached entries |
Table Schema
Sockudo auto-creates the table and migrates new columns automatically. The table includes:
id,key,secret- Core credentialsmax_connections,max_client_events_per_second- Limitsenable_client_messages,enabled- Flagswebhooks- JSON column for webhook definitionsallowed_origins- JSON column for origin restrictions- All optional per-app limit fields
PostgreSQL Driver
Same features as MySQL, adapted for PostgreSQL. Uses JSONB columns and PostgreSQL-native syntax.
{
"app_manager": {
"driver": "postgres"
},
"database": {
"postgres": {
"host": "localhost",
"port": 5432,
"username": "sockudo",
"password": "secret",
"database": "sockudo"
}
}
}
APP_MANAGER_DRIVER=postgres
DATABASE_POSTGRES_HOST=localhost
DATABASE_POSTGRES_PORT=5432
DATABASE_POSTGRES_USERNAME=sockudo
DATABASE_POSTGRES_PASSWORD=secret
DATABASE_POSTGRES_DATABASE=sockudo
Connection pooling and query caching work identically to MySQL.
DynamoDB Driver
Stores apps in a single DynamoDB table with the id field as the partition key.
{
"app_manager": {
"driver": "dynamodb"
},
"database": {
"dynamodb": {
"region": "us-east-1",
"table_name": "sockudo-applications"
}
}
}
For local development with DynamoDB Local:
DATABASE_DYNAMODB_ENDPOINT_URL=http://localhost:8000
Authentication
DynamoDB uses standard AWS credential resolution:
- Environment variables:
AWS_ACCESS_KEY_ID+AWS_SECRET_ACCESS_KEY - AWS profile:
aws_profile_namein config - IAM role (ECS task role, EC2 instance profile)
AWS_ACCESS_KEY_ID=AKIA...
AWS_SECRET_ACCESS_KEY=secret...
ScyllaDB Driver
High-performance driver using ScyllaDB (or Apache Cassandra). Automatically creates the keyspace, table, and secondary indexes.
{
"app_manager": {
"driver": "scylladb",
"scylladb": {
"nodes": ["10.0.0.1:9042", "10.0.0.2:9042"],
"keyspace": "sockudo",
"table_name": "applications",
"username": "cassandra",
"password": "cassandra",
"replication_class": "NetworkTopologyStrategy",
"replication_factor": 3
}
}
}
| Setting | Default | Description |
|---|---|---|
nodes | ["127.0.0.1:9042"] | Contact points |
keyspace | sockudo | Keyspace name |
table_name | applications | Table name |
replication_class | SimpleStrategy | Replication strategy |
replication_factor | 3 | Replication factor |
A secondary index on the key column is created automatically for fast key-based lookups.
App Manager Caching
All database-backed drivers (MySQL, PostgreSQL, DynamoDB, ScyllaDB) are automatically wrapped in a caching layer. This is separate from the cache driver and is configured under app_manager.cache:
{
"app_manager": {
"cache": {
"enabled": true,
"ttl": 300
}
}
}
| Setting | Default | Description |
|---|---|---|
enabled | true | Enable app lookup caching |
ttl | 300 | Cache TTL in seconds |
The cache is:
- Read-through: on cache miss, fetches from the database and stores in cache.
- Write-through: on app update/delete, invalidates cache immediately.
- Keyed by both app ID and app key for fast lookups in either direction.
App Configuration Fields
Each app supports these fields:
| Field | Type | Default | Description |
|---|---|---|---|
id | string | required | Unique app identifier |
key | string | required | Public app key (used in client connections) |
secret | string | required | Secret for signing (never sent to clients) |
enabled | bool | true | Accept connections for this app |
enable_client_messages | bool | false | Allow client-to-client events |
max_connections | u32 | 100 | Max simultaneous WebSocket connections |
max_client_events_per_second | u32 | 100 | Client event rate limit |
max_read_requests_per_second | u32? | 100 | Read API rate limit |
max_backend_events_per_second | u32? | 100 | Backend event rate limit |
max_presence_members_per_channel | u32? | 100 | Max users per presence channel |
max_presence_member_size_in_kb | u32? | 100 | Max presence user info size |
max_channel_name_length | u32? | 100 | Max channel name length |
max_event_channels_at_once | u32? | 100 | Max channels per broadcast |
max_event_name_length | u32? | 100 | Max event name length |
max_event_payload_in_kb | u32? | 100 | Max event payload size |
max_event_batch_size | u32? | 100 | Max events per batch |
enable_user_authentication | bool? | false | Require user auth |
enable_watchlist_events | bool? | false | Enable watchlist events |
allowed_origins | string[]? | null | Restrict WebSocket origins |
webhooks | Webhook[]? | null | Webhook definitions |
channel_delta_compression | object? | null | Per-channel delta config overrides |
Choosing a Driver
- Development: Use
memorywith inline apps or env vars. - Single-node production:
mysqlorpostgreswith connection pooling. - Multi-node production: Any database driver works since all nodes read from the same source.
- AWS-native:
dynamodbwith IAM roles. - High-throughput:
scylladbfor lowest latency at scale.