Introduction¶
DeepSeek Harness (DSH) session persistence commonly uses file backends such as JSONL. When you need higher data reliability, separated read/write capabilities, or distributed deployment, using a database as the backend is a more robust approach. The dsh-session-persistence-mysql plugin implements the SessionPersistence interface, persists the event-sourcing SessionEvent log to MySQL, and provides read/write behavior equivalent to the JSONL backend.
Plugin Overview¶
This plugin is maintained by sandersyao and is an open source project under the MIT license. It acts as a concrete implementation (seam) for DSH, registers ctx.sessionPersistence, and supports features such as transactional append, tear-free tail, and crash recovery.
Installation and Enablement¶
Import and register the plugin in code:
import { MysqlSessionPersistence } from '@sandersyao/dsh-session-persistence-mysql'
await ctx.plugin(MysqlSessionPersistence, {
connection: { tablePrefix: process.env.SESSION_TABLE_PREFIX ?? process.env.MYSQL_TABLE_PREFIX },
})
After registration, ctx.sessionPersistence becomes MySQL-driven.
Core Capabilities¶
- MySQL persistence backend: Stores session events as an append-only log in the database.
- Read/write separation support: After configuring a read database, read operations use the read connection pool and write operations use the write connection pool. If no read database is configured, reads and writes share the write connection.
- Transactional append and tear-free tail: Events are appended transactionally, ensuring continuous log ordering and atomicity, and avoiding the tearing issues that can occur during file writes.
- Crash recovery: Supports recovering unfinished sessions after a crash by synthesizing close markers; committed records are not rewritten.
- Lazy instantiation: The session header is atomically written together with the event batch only when the first event is appended.
- Deadlock retry: When an
ER_LOCK_DEADLOCK(1213) error is encountered, bounded backoff retries are performed. - Schema and migration: Automatically tests the connection, creates tables, and validates the schema version at startup.
Configuration and Usage¶
The plugin is configured through environment variables. Configuration items are divided into plugin-specific SESSION_* and generic MYSQL_* variables. The plugin prioritizes SESSION_* values and falls back to MYSQL_* values when they are not set. This approach allows the same MySQL deployment to be independently configured by multiple plugins (for example, using different databases or table prefixes).
Configuration priority examples:
- SESSION_HOST / MYSQL_HOST: write host, defaults to 127.0.0.1.
- SESSION_USER / MYSQL_USER: database user, required.
- SESSION_DATABASE / MYSQL_DATABASE: target database, required.
- SESSION_TABLE_PREFIX / MYSQL_TABLE_PREFIX: table prefix, defaults to empty, required.
- SESSION_READ_HOST / MYSQL_READ_HOST: read database host; if empty, reads and writes share the write connection.
- SESSION_SCHEMA_AUTO_MIGRATE / MYSQL_SCHEMA_AUTO_MIGRATE: whether to automatically migrate the schema, defaults to true.
Enable automatic migration:
SESSION_SCHEMA_AUTO_MIGRATE=true
SESSION_HOST=127.0.0.1
SESSION_USER=root
SESSION_PASSWORD=secret
SESSION_DATABASE=dsh_session
SESSION_TABLE_PREFIX=dsh_
Storage Layout¶
The plugin creates two data tables and one metadata table in MySQL (determined by the table prefix):
- ${prefix}sessions: stores session headers (SessionHeader). It is written only when the first event is appended and is created lazily.
- ${prefix}events: append-only log table, primary key is (session_id, seq).
- ${prefix}_meta: stores the applied schema version.
Ecosystem and Companion Plugins¶
This plugin is typically used together with the following plugins to form a complete distributed DSH deployment:
- dsh-storage-mysql: switches the default storage backend to MySQL.
- dsh-credentials-mysql: switches the default credentials backend to MySQL.
- dsh-workspace-bootstrap: declaratively initializes the default workspace, ensuring normal startup with an empty database.
Known Limitations and Notes¶
- No deletion/archive API: The plugin interface does not provide methods for deleting or archiving sessions. Storage cleanup must be performed offline at the database level using SQL
DELETEoperations. list()lacks pagination and filtering: Thelist()method does not support pagination or filter conditions; it only returns all sessions.- Cross-process lease mode limitations: The
cluster.leasemode only supports single-primary writes. Use it carefully in multi-primary or read/write separation topologies. - Plaintext storage: Session events are stored in plaintext by default. Sensitive content (conversations and tool results) must rely on application-layer encryption or MySQL Transparent Data Encryption (TDE).
- TLS enforcement deferred:
SESSION_SSL_REQUIREDis currently a reserved configuration and does not enforce TLS encryption yet. - Version lock: The plugin depends on the
^0.2.0-rc.xversions of@deepseek-ai/dsh-session-persistenceand@deepseek-ai/dsh-session.
Conclusion¶
dsh-session-persistence-mysql provides a reliable MySQL-based session storage solution for DSH, suitable for production environments that require transaction guarantees and high availability. Before using it, understand its limitations regarding deletion, pagination, and encryption, and configure read/write separation or TLS according to your scenario.