Chronos Tutorials

How and where Chronos stores data

Saulius
2026-04-27
10 min

Summary

This is a part of Chronos tutorial series.

Chronos by Intelligex is an open source, self-hosted control plane for AI agents and MCP tools — application state and data lives on your own infrastructure. This tutorial covers exactly where that state lives: the .chronos directory on disk, the relational database backend, encryption-at-rest for secrets, the blob storage layer for uploaded files, and the log-file layout. It applies equally to local development and production-shaped deployments.

Overview

Chronos persists data in two primary locations:

  1. The .chronos directory — a local filesystem directory holding the SQLite database (when used), the encryption key, file uploads, and logs.
  2. The relational database — a TypeORM-backed schema supporting SQLite and PostgreSQL.

This split lets developers start with zero configuration (SQLite + local filesystem) and scale up to production-grade backends (Postgres + S3) by changing environment variables, not code.

The .chronos directory

Automatic initialisation

When Chronos starts, it creates .chronos/ in the user's home directory if it doesn't already exist:

// DataSource.ts
let chronosPath = path.join(getUserHome(), '.chronos');
if (!fs.existsSync(chronosPath)) {
  fs.mkdirSync(chronosPath);
}

Directory layout

~/.chronos/
├── database.sqlite      # SQLite database (default)
├── encryption.key       # AES key for credential encryption
├── storage/             # Blob storage for uploaded files
│   └── {orgId}/
│       └── {agentflowId}/
│           └── {chatId}/
│               └── {files}
└── logs/                # Application logs (when LOG_PATH is unset)
    ├── server.log
    ├── server-error.log
    └── server-requests.log.jsonl

Customise paths via environment variables

Every path can be overridden — useful for containerised or cloud deployments where you want state on a mounted volume:

Environment variableDefaultPurpose
DATABASE_PATH~/.chronos/Directory containing database.sqlite
SECRETKEY_PATH~/.chronos/Directory containing encryption.key
BLOB_STORAGE_PATH~/.chronos/storageLocal blob storage root
LOG_PATH~/.chronos/logsApplication logs

Database architecture

Supported backends

Chronos uses TypeORM as its ORM layer. These backends ship out of the box:

  • SQLite (default) — zero-configuration, file-based.
  • PostgreSQL — recommended for production type deployments.

Selection is controlled via DATABASE_TYPE:

switch (process.env.DATABASE_TYPE) {
  case 'sqlite':    // ~/.chronos/database.sqlite
  case 'postgres':  // DATABASE_HOST, DATABASE_PORT, …
  default:          // falls back to SQLite
}

Entity schema

Chronos defines 22 database entities that model the entire application state. Two of those — Agent and MCPServer — were recently added as part of the Agent Registry and MCP Gateway work.

Core flow entities

EntityPurposeKey fields
ChatFlowAgentflow / canvas configurationsid, name, flowData (JSON), deployed, type
ChatMessageConversation messagesrole, content, sourceDocuments, usedTools, agentReasoning
ChatMessageFeedbackUser feedback on responseschatflowid, messageId, rating, content
ExecutionFlow execution recordsLinks messages to execution context

Agent registry and MCP gateway

EntityPurposeKey fields
AgentRegistered agents — both BUILT_IN (canvas) and HTTP (external) runtime typesname, slug, runtimeType, serviceEndpoint, outboundAuth, callbackToken, allowedTools, status
MCPServerRegistered MCP servers brokered through the Chronos gatewayname, slug, transport, url, outboundAuth, allowedTools, status, requestHeaders

Both rows are BUILT_IN-flavoured for canvas agents and operator-created for HTTP agents and MCP servers.

Security and configuration

EntityPurposeKey fields
CredentialEncrypted API keysname, credentialName, encryptedData
VariableGlobal variablesname, value, type (string/runtime)
ApiKeyExternal access API keysAuthentication tokens for API access
UserUser accountsAuthentication and authorisation

Document management

EntityPurposeKey fields
DocumentStoreDocument store metadataname, description, loaders, vectorStoreConfig
DocumentStoreFileChunkIndexed document chunksIndividual chunks for vector stores
UpsertHistoryVector indexing historyTracks document upsert operations

AI components

EntityPurposeKey fields
ToolCustom tool configurationsTool definitions for agents
AssistantAI assistant configsAssistant configurations
CustomTemplateMessage templatesReusable prompt templates

Evaluation and analytics

EntityPurposeKey fields
DatasetEvaluation datasetsDataset metadata
DatasetRowDataset entriesIndividual test cases
EvaluationEvaluation configurationsEvaluation setup
EvaluationRunEvaluation executionsRun results
EvaluatorEvaluator definitionsEvaluation criteria
LeadLead capture dataCaptured user information

Schema migrations

Schema evolution is handled through TypeORM migrations, organised per backend:

packages/server/src/database/migrations/
├── sqlite/
├── postgres/

Migrations run controllably on startup.

File storage architecture

Storage backends

Chronos supports three blob backends for uploaded files:

  1. Local (default) — files stored under ~/.chronos/storage/.
  2. S3 compatible — AWS S3 or any S3-compatible service (R2, MinIO, etc.).
  3. GCS — Google Cloud Storage.

Selection is controlled via STORAGE_TYPE:

export const getStorageType = (): string => {
  return process.env.STORAGE_TYPE ? process.env.STORAGE_TYPE : 'local';
};

Credential encryption

Credentials (LLM API keys, MCP server tokens, agent outbound-auth secrets) are stored as ciphertext in the Credential table. Plaintext values do not reach the databases.

The encryption key lives at ~/.chronos/encryption.key (can be owerritten by SECRETKEY_PATH env variable).

On first start, Chronos generates a fresh key if none exists. Treat this file like any other production secret — back it up, rotate when compromised, and ensure the path is on a mounted volume in any containerised deployment so the key persists across restarts.

Logging architecture

Winston with daily rotation

Logging uses Winston with file rotation:

  • server.log — general application logs.
  • server-error.log — error-level logs.
  • server-requests.log.jsonl — HTTP request logs in JSONL format.

Log levels

Supported log levels: DEBUG, VERBOSE, INFO, WARN, ERROR.

Sensitive-data sanitisation

Sensitive fields are stripped from logs before they're written:

  • Passwords and secrets.
  • API keys and tokens.
  • Authorization headers.

The same pipeline emits the audit lines from the MCP gateway event=mcp.tool.invoke — pipe these into your existing log aggregator. Chronos will introduce the persistent tool_invocation_audit concept in the near future.

Next steps

  • Database for production. Postgres is the recommended default; SQLite is fine for single-host or development. Hovever, some users have managed to productionise SQLite setup in production type environments as well.
  • Mount your state. In Docker / Kubernetes, mount ~/.chronos/ or override DATABASE_PATH, SECRETKEY_PATH, BLOB_STORAGE_PATH onto persistent storage so it survives container restarts.
  • Move blobs off the local disk. Set STORAGE_TYPE=s3 (or gcs) for any deployment with more than one Chronos instance — local-disk storage can't be shared across replicas.

Similar Chronos tutorials


#Data Management#Chronos#Intelligex#Self Hosting

Intelligex Monthly

Join hundreds of developers, tech leads and product owners. We send a short, text-only monthly email with recent product reviews.

No spam • Unsubscribe anytime