# What Is the Difference Between `runtime-opencode-config-store` and Environment Variable Config Injection?

> Understand the difference between runtime-opencode-config-store and environment variable config injection. Learn how to manage mutable and immutable application configurations effectively.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: deep-dive
- Published: 2026-08-22

---

**The `runtime-opencode-config-store` provides a mutable, SQLite-backed configuration store that applications can read from and write to during execution, while environment variable config injection supplies static, immutable values loaded from `process.env` when the Node.js process starts.**

The different-ai/openwork repository supports two distinct configuration strategies for managing OpenCode settings: a dynamic runtime store for mutable data and static environment variables for deployment-specific secrets. Understanding the architectural differences between these approaches ensures you select the correct method for dynamic provider credentials versus immutable deployment parameters.

## Core Architectural Differences

### Mutable Runtime Configuration

The **runtime-opencode-config-store** persists configuration in a lightweight SQLite database located in the runtime's data directory. Implemented in [`dev/apps/server/src/runtime-opencode-config-store.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/runtime-opencode-config-store.ts), this module exports `readRuntimeOpencodeConfig` and `writeRuntimeOpencodeConfig` functions that enable on-demand configuration updates without requiring process restarts. This approach supports dynamic features such as live plugin installation, real-time provider credential rotation, and user-driven MCP (Model Context Protocol) management.

### Static Environment Variable Injection

**Environment variable config injection** relies on Node.js `process.env` values captured immediately upon process initialization. These values remain immutable during execution—modifying them requires restarting the process with a new environment. This method is ideal for sensitive secrets like `OPENWORK_API_KEY` or feature flags that must remain constant throughout the application lifecycle, as referenced in [`openwork-runtime-config.ts`](https://github.com/different-ai/openwork/blob/main/openwork-runtime-config.ts).

## Implementation Details in OpenWork

### The Runtime Store Module

In [`dev/apps/server/src/runtime-opencode-config-store.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/runtime-opencode-config-store.ts), the store implements a read-write interface against SQLite:

```typescript
import {
  readRuntimeOpencodeConfig,
  writeRuntimeOpencodeConfig,
} from "./runtime-opencode-config-store.js";

// Example: Adding a new provider at runtime
async function addProvider(name: string, apiKey: string) {
  const cfg = await readRuntimeOpencodeConfig();
  cfg.providers ??= {};
  cfg.providers[name] = { apiKey };
  await writeRuntimeOpencodeConfig(cfg);
}

```

The SQLite file resides in the runtime's data directory, allowing the application to persist changes across sessions while maintaining ACID guarantees for concurrent operations.

### Environment Variable Handling

Configuration via environment variables occurs before any OpenWork modules execute. The [`openwork-runtime-config.ts`](https://github.com/different-ai/openwork/blob/main/openwork-runtime-config.ts) file handles the initial parsing of `process.env` values:

```typescript
// Values loaded at startup from process.env
const apiKey = process.env.OPENWORK_API_KEY!;
const model = process.env.OPENWORK_MODEL ?? "openai/gpt-4";
const logLevel = process.env.OPENWORK_LOG_LEVEL ?? "info";

```

Since these values are frozen at startup, they provide a secure baseline for constants that should not change during execution, including credentials injected by CI/CD pipelines.

## When to Use Each Approach

Use the **runtime-opencode-config-store** when:

- Configuration must evolve without restarting the server
- Implementing user-facing features like plugin management or dynamic MCP configuration
- Running integration tests that need to inspect or modify configuration state, as demonstrated in [`runtime-opencode-config-store.test.ts`](https://github.com/different-ai/openwork/blob/main/runtime-opencode-config-store.test.ts)

Use **environment variable config injection** when:

- Storing sensitive secrets that should never be writable by the application code itself
- Defining static feature flags or model overrides (`OPENWORK_MODEL_OVERRIDES`)
- Operating in containerized environments where configuration is determined at deployment time

## Practical Code Examples

### Dynamic Updates with the Runtime Store

```typescript
// File: dev/apps/server/src/runtime-opencode-config-store.ts
const cfg = await readRuntimeOpencodeConfig();
cfg.providers.anthropic.apiKey = "sk-new-key";
await writeRuntimeOpencodeConfig(cfg); // Immediately persisted to SQLite

```

Components like [`cloud-provider-sync.ts`](https://github.com/different-ai/openwork/blob/main/cloud-provider-sync.ts) consume this store to synchronize provider credentials dynamically.

### Static Configuration via Environment

```typescript
// In .env file
OPENWORK_API_KEY=abc123
OPENWORK_MODEL=anthropic/claude-v2

// In application bootstrap code
const apiKey = process.env.OPENWORK_API_KEY!;
// Value remains constant for this process lifetime

```

The end-to-end tests in [`runtime-config-migrate.e2e.test.ts`](https://github.com/different-ai/openwork/blob/main/runtime-config-migrate.e2e.test.ts) demonstrate migration patterns from environment-based to runtime-store configuration.

## Summary

- **Mutability**: The runtime store allows dynamic updates via `writeRuntimeOpencodeConfig`, while environment variables are immutable after process start
- **Persistence**: Runtime configuration writes to a SQLite database; environment variables exist only in process memory
- **Timing**: Runtime store reads occur on-demand during execution; environment variables load exactly once at startup
- **Use Cases**: Use the store for dynamic provider management and plugins; use environment variables for secrets and static deployment configuration
- **Key Files**: Core implementation resides in [`dev/apps/server/src/runtime-opencode-config-store.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/runtime-opencode-config-store.ts), while environment handling appears in [`openwork-runtime-config.ts`](https://github.com/different-ai/openwork/blob/main/openwork-runtime-config.ts)

## Frequently Asked Questions

### Can I modify environment variables after the OpenWork server starts?

No. Environment variables are captured when the Node.js process initializes and remain static throughout execution. To change configuration values loaded from `process.env`, you must restart the server with updated environment variables or migrate to the runtime store pattern shown in [`runtime-config-migrate.e2e.test.ts`](https://github.com/different-ai/openwork/blob/main/runtime-config-migrate.e2e.test.ts).

### How does the runtime store handle concurrent writes?

The `runtime-opencode-config-store` leverages SQLite's built-in concurrency mechanisms to handle simultaneous read and write operations safely. The `writeRuntimeOpencodeConfig` function ensures atomic updates to the configuration file, preventing data corruption during concurrent access.

### Where is the runtime configuration physically stored?

According to the source code in [`dev/apps/server/src/runtime-opencode-config-store.ts`](https://github.com/different-ai/openwork/blob/main/dev/apps/server/src/runtime-opencode-config-store.ts), the runtime store persists data in a SQLite database file located within the runtime's data directory. This ensures configuration survives individual requests but remains scoped to the specific deployment instance.

### Should I use environment variables or the runtime store for API keys?

Store sensitive API keys in environment variables for security immutability, but reference them through the runtime store if your application requires dynamic key rotation without restarts. The test suite in [`runtime-config-global-providers.test.ts`](https://github.com/different-ai/openwork/blob/main/runtime-config-global-providers.test.ts) demonstrates secure patterns for combining both approaches.