Singularity
API Reference

Configuration

Complete reference for all Singularity configuration options — Settings fields, Celery configuration, database pool tuning, logging levels, and Redis connection settings.

Singularity uses Pydantic Settings for configuration management. All settings are loaded from environment variables or a .env file at the project root.


Settings Class

config.settings.Settings

The Settings class inherits from pydantic_settings.BaseSettings. A module-level singleton settings is created at import time and shared across the entire application.

from singularity.config import settings

# Access any field
db_url = settings.database_url
env = settings.environment

Settings Fields

FieldTypeDefaultDescription
environmentstr"dev"Application environment (ENVIRONMENT). Accepted values: dev, beta, prod. Controls logging levels and worker pool type.
database_urlstr"postgresql+asyncpg://...localhost:5432/postgres"PostgreSQL connection URL (DATABASE_URL). Must use the asyncpg driver for async support.
celery_broker_urlstr"redis://localhost:6379/0"Redis URL for the Celery message broker (CELERY_BROKER_URL). Also used for RPC spec publishing, heartbeat, and WebSocket notification pub/sub.
celery_result_backendstr"redis://localhost:6379/0"Redis URL for Celery task result storage (CELERY_RESULT_BACKEND).
jwt_secretstr"dummy_value"Secret key for JWT token signing and verification (JWT_SECRET).
rpc_base_urlstr"http://localhost:8000"Base URL remote callers use to reach this deployment (RPC_BASE_URL). Published to Redis for discovery, and combined with the app's prefix to build endpoint URLs.
rpc_timeoutfloat30.0Timeout in seconds for outbound remote RPC calls (RPC_TIMEOUT).
rpc_heartbeat_intervalint30Seconds between Redis re-registration and peer re-scan (RPC_HEARTBEAT_INTERVAL).
rpc_spec_ttlint60TTL in seconds on published RPC specs (RPC_SPEC_TTL). Keep it above the heartbeat interval, or peers will briefly disappear between beats.
rpc_api_keystr""Key sent as X-API-Key on outbound RPC calls (RPC_API_KEY).
rpc_api_keysstr""Comma-separated keys accepted on inbound RPC calls (RPC_API_KEYS). Falls back to rpc_api_key when empty.
rpc_require_api_keyboolFalseReject inbound RPC requests without a valid X-API-Key (RPC_REQUIRE_API_KEY). See Securing Inbound RPC.

Pydantic Config

SettingTypeDefaultDescription
env_filestr".env"Path to the environment file
env_file_encodingstr"utf-8"Encoding of the environment file

Example .env File

ENVIRONMENT=dev
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/mydb
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/1
JWT_SECRET=your-secret-key-here
RPC_BASE_URL=http://localhost:8000
RPC_TIMEOUT=30
RPC_HEARTBEAT_INTERVAL=30
RPC_SPEC_TTL=60
# Set on both sides to authenticate calls between deployments
RPC_API_KEY=
RPC_REQUIRE_API_KEY=false

The default values for database_url, celery_broker_url, and jwt_secret are placeholder values. Always set these via environment variables or .env in any non-local environment.

Adding Custom Settings

Extend the Settings class in singularity/config.py to add your own fields:

class Settings(BaseSettings):
    # ... existing fields ...

    # Custom fields
    stripe_api_key: str = ""
    stripe_webhook_secret: str = ""
    max_upload_size: int = 10_485_760  # 10MB
    billing_host_url: str = "http://localhost:8001"
    billing_api_key: str = ""

All custom fields automatically support environment variable loading. The env var name is the uppercased field name (e.g. STRIPE_API_KEY).


Celery Configuration

common.q

Celery is configured in singularity/common/q.py. The configuration is applied via celery_app.conf.update().

Configuration Keys

KeyValueDescription
task_serializer"json"Serialization format for task messages
accept_content["json"]Accepted content types for deserialization
result_serializer"json"Serialization format for task results
timezone"UTC"Timezone for Celery scheduling
enable_utcTrueUse UTC for all timestamps
task_track_startedTrueTrack when tasks transition to the STARTED state
task_time_limit3600Global hard timeout in seconds (1 hour)
worker_pool"threads" / "prefork"Worker pool implementation. Uses threads in dev for easier debugging, prefork in other environments.
worker_concurrency2Default number of concurrent workers
worker_prefetch_multiplier1Number of messages to prefetch per worker. Set to 1 for fair task distribution.
beat_scheduler"redbeat.RedBeatScheduler"Redis-backed beat scheduler for schedule persistence across restarts
redbeat_redis_urlsettings.celery_broker_urlRedis URL for RedBeat schedule storage
redbeat_key_prefix"celery:beat:"Key prefix for RedBeat entries in Redis
broker_connection_retry_on_startupTrueRetry broker connection if unavailable at startup
beat_schedule{}Periodic task schedule (empty by default; add entries as needed)

The singularity tasks worker CLI command lets you override worker_pool (--pool) and worker_concurrency (--concurrency) at runtime without changing the configuration file.


Database Pool Configuration

database.postgres

Singularity configures two SQLAlchemy engines: an async engine for FastAPI endpoints and a sync engine for Celery tasks.

Async Engine (FastAPI)

OptionValueDescription
poolclassAsyncAdaptedQueuePoolAsync-compatible connection pool
pool_size20Maximum number of persistent connections in the pool
pool_timeout3600Seconds to wait for a connection from the pool before raising an error
pool_pre_pingTrueIssue a SELECT 1 before reusing a connection to verify it is still alive
echoFalseDisable SQL statement logging

Sync Engine (Celery Workers)

OptionValueDescription
poolclassQueuePoolStandard synchronous connection pool
pool_size100Maximum number of persistent connections
max_overflow200Maximum number of connections beyond pool_size allowed temporarily
pool_timeout30Seconds to wait for a connection from the pool
pool_pre_pingTrueVerify connections before reuse
echoFalseDisable SQL statement logging

Session Configuration

Both session factories use expire_on_commit=False to allow access to object attributes after a commit without requiring a refresh.

# Async session (for services)
async_session = async_sessionmaker[AsyncSession](async_engine, class_=AsyncSession, expire_on_commit=False)

# Sync session (for Celery tasks)
sync_session = sessionmaker[Session](sync_engine, class_=Session, expire_on_commit=False)

get_db() Dependency

The get_db() async generator is available as a FastAPI dependency for direct use in route handlers:

from singularity.db import get_db

@router.get("/users")
async def list_users(db: AsyncSession = Depends(get_db)):
    result = await db.execute(select(User))
    return result.scalars().all()

The sync database URL is derived automatically from settings.database_url by replacing postgresql+asyncpg:// with postgresql://. No separate env var is needed.


Logging Configuration

common.logger

Singularity uses Loguru for structured logging. The logging level and targets are determined by the environment setting.

Logging Levels per Environment

devbetaprod
LevelDEBUGDEBUGINFO
Targetsstderr + filestderrstderr
DetailsConsole + logs/app.log (10 MB rotation)Console-only debug loggingConsole-only, info level and above

Usage

from singularity.common.logger import log as logger

# Structured logging
logger.info("Task completed", task_name="send_email", duration_ms=150)
logger.error("Payment failed", order_id="123", error="Insufficient funds")
logger.debug("RPC call", caller="orders", target="payments", method="charge")

Loguru supports rich contextual logging via keyword arguments. Each key-value pair becomes a structured field in the log output.


Redis Connection Settings

Redis is used for three purposes in Singularity:

PurposeConfig FieldRedis Key Pattern
Celery broker (task queue)celery_broker_urlManaged by Celery
Celery result backendcelery_result_backendManaged by Celery
RPC service discoverycelery_broker_urlsingularity:rpc:services:{name}, singularity:rpc:spec
RedBeat schedulercelery_broker_urlcelery:beat:*
WebSocket notificationscelery_broker_urlPub/sub channel: task_notifications

All Redis connections currently share the same URL (celery_broker_url). If you need to separate them (e.g. different Redis instances for broker vs. RPC), you can add additional fields to the Settings class and update the relevant modules.

RPC Redis Keys

KeyTTLContentSet By
singularity:rpc:services:{name}60sJSON spec for a single service (base_url, blacklist, methods)RPCRegistry.publish_to_redis()
singularity:rpc:spec60sFull RPC spec for all local servicesRPCRegistry.publish_to_redis()

RPC Heartbeat

SettingValueDescription
Interval30 secondsHow often the heartbeat refreshes Redis keys
TTL60 secondsTime-to-live for each Redis key
Disable flag--no-heartbeatCLI flag on app.py that sets SINGULARITY_NO_HEARTBEAT=1

If the heartbeat is disabled, RPC keys will expire after 60 seconds and remote services will no longer be discoverable.


Environment Variable Summary

Complete list of all environment variables recognized by Singularity:

VariableTypeDefaultUsed By
ENVIRONMENTstr"dev"Settings, Logger, Celery pool selection
DATABASE_URLstr(required)SQLAlchemy engines (async + sync)
CELERY_BROKER_URLstr(required)Celery, RPC Redis, RedBeat, WebSocket notifications
CELERY_RESULT_BACKENDstr(required)Celery result storage
JWT_SECRETstr(required)JWT authentication
RPC_BASE_URLstr"http://localhost:8000"RPC spec generation, endpoint prefix
SINGULARITY_NO_HEARTBEATstr(unset)Set to "1" to disable the RPC heartbeat (set automatically by --no-heartbeat)