Configuration Reference

Grove projects are configured through a grove.toml file at the project root and through environment variables. Configuration controls module discovery, database connections, server settings, credential store behavior, and runtime defaults. All settings have sensible defaults for local development.

Prerequisites: CLI Reference, Database Backends, Server. What you'll learn: Every configuration option available in grove.toml and via environment variables, with defaults and examples.


Configuration File

The configuration file is named grove.toml and lives at the root of your project directory:

my-project/
  grove.toml          <-- project configuration
  order/
    actions.grove
  customer/
    actions.grove

Grove uses TOML syntax. If no grove.toml is found, default values are used for all settings.

Project Settings

project_id = "my-app"
KeyTypeDefaultDescription
project_idStringrequiredThe project identifier. Used as the first segment of every resource name and persisted in the deploy tarball so the platform knows which project a deploy belongs to.

manzano init <name> writes project_id = "<name>". On the first successful manzano deploy, the CLI replaces this with the server-minted form project_id = "prj_<ksuid>" (preserving comments and formatting in the file). Subsequent deploys read that ID and use it to route the tarball to the correct project. See CLI Reference — deploy for the first-deploy flow.

project_id must match the pattern [A-Za-z0-9_]+. Lowercase names and server-minted prj_... IDs both pass.

Module Discovery

[modules]
paths = ["order", "customer", "shared/types"]
exclude = ["experimental"]
KeyTypeDefaultDescription
pathsList<String>auto-discoverExplicit list of module directories (relative to project root)
excludeList<String>[]Directories to exclude from auto-discovery

When paths is not set, Grove auto-discovers modules by scanning for directories containing .grove files.

Per-Module Configuration

[modules.order]
table_prefix = "shop_order"

[modules.customer]
table_prefix = "cust"
KeyTypeDefaultDescription
table_prefixStringmodule nameCustom database table prefix for this module

Database Settings

[database]
backend = "postgres"
connection = "postgres://grove:secret@localhost:5432/grovedb"
KeyTypeDefaultDescription
backendStringnone (required for db operations)Database backend: sqlite, postgres, mysql, tidb
connectionStringnone (required for db operations)Database connection string

Connection Pool

[database.pool]
max_connections = 20
min_connections = 5
idle_timeout_seconds = 300
max_lifetime_seconds = 3600
acquire_timeout_seconds = 30
KeyTypeDefaultDescription
max_connectionsInt10Maximum number of connections in the pool
min_connectionsInt1Minimum idle connections to maintain
idle_timeout_secondsInt600Close idle connections after this many seconds
max_lifetime_secondsInt3600Maximum lifetime of a connection in seconds
acquire_timeout_secondsInt30Timeout for acquiring a connection from the pool

Server Settings

[server]
listen = "127.0.0.1:3000"
cors_origin = "http://localhost:5173"
read_timeout_ms = 30000
write_timeout_ms = 30000
max_body_size = 1048576
workers = 4
KeyTypeDefaultDescription
listenString"127.0.0.1:3000"Address and port to bind to
cors_originStringnoneAllowed CORS origin (omit to disable CORS)
read_timeout_msInt30000Request read timeout in milliseconds
write_timeout_msInt30000Response write timeout in milliseconds
max_body_sizeInt1048576Maximum request body size in bytes (default 1 MB)
workersIntCPU countNumber of server worker threads
shutdown_timeout_secondsInt30Graceful shutdown timeout in seconds

Worker Settings

[worker]
concurrency = 10
poll_interval_ms = 1000
retry_max_attempts = 5
retry_initial_delay_ms = 1000
retry_max_delay_ms = 60000
retry_backoff_multiplier = 2.0
KeyTypeDefaultDescription
concurrencyInt10Maximum concurrent workflow/activity executions
poll_interval_msInt1000How often to poll for new work, in milliseconds
retry_max_attemptsInt5Maximum retry attempts for failed activities
retry_initial_delay_msInt1000Initial retry delay in milliseconds
retry_max_delay_msInt60000Maximum retry delay in milliseconds
retry_backoff_multiplierFloat2.0Exponential backoff multiplier

Credential Store Settings

[credentials]
backend = "file"
path = ".grove/credentials"
KeyTypeDefaultDescription
backendString"file"Credential store backend: file or database
pathString".grove/credentials"File path for the file-based credential store

When backend = "database", credentials are stored in the same database configured in [database].

Logging

[logging]
level = "info"
format = "json"
KeyTypeDefaultDescription
levelString"warn"Log level: error, warn, info, debug, trace
formatString"text"Log format: text or json

Testing

[testing]
timeout_seconds = 30
parallel = true
backend = "sqlite"
connection = ":memory:"
KeyTypeDefaultDescription
timeout_secondsInt30Per-test timeout
parallelBooltrueRun tests in parallel
backendStringnoneDefault database backend for tests
connectionStringnoneDefault database connection for tests

Environment Variables

All configuration values can be overridden by environment variables. Environment variables take precedence over grove.toml values.

Naming Convention

Environment variables follow the pattern GROVE_<SECTION>_<KEY> in uppercase, with dots and nesting replaced by underscores:

grove.toml KeyEnvironment Variable
project.nameGROVE_PROJECT_NAME
database.backendGROVE_DATABASE_BACKEND
database.connectionGROVE_DATABASE_CONNECTION
database.pool.max_connectionsGROVE_DATABASE_POOL_MAX_CONNECTIONS
server.listenGROVE_LISTEN
server.cors_originGROVE_CORS_ORIGIN
server.workersGROVE_WORKERS
worker.concurrencyGROVE_WORKER_CONCURRENCY
logging.levelGROVE_LOG_LEVEL

Special Environment Variables

VariableDescription
GROVE_MASTER_KEYMaster encryption key for the credential store (base64-encoded, 256-bit)
GROVE_ENVEnvironment name: development, staging, production (affects defaults)
GROVE_CONFIGPath to a custom grove.toml file (overrides default discovery)

Environment-Specific Defaults

When GROVE_ENV is set, certain defaults change:

Settingdevelopmentstagingproduction
logging.level"debug""info""warn"
logging.format"text""json""json"
server.cors_origin"*"nonenone
database.pool.max_connections51020

Full Example

[project]
name = "ecommerce"
version = "1.2.0"

[modules]
paths = ["order", "customer", "inventory", "shared/types"]

[modules.order]
table_prefix = "shop_order"

[database]
backend = "postgres"
connection = "postgres://grove:secret@localhost:5432/ecommerce"

[database.pool]
max_connections = 20
min_connections = 5

[server]
listen = "0.0.0.0:3000"
cors_origin = "https://app.example.com"
workers = 8

[worker]
concurrency = 20
retry_max_attempts = 10

[credentials]
backend = "database"

[logging]
level = "info"
format = "json"

[testing]
timeout_seconds = 60
backend = "sqlite"
connection = ":memory:"

Precedence Order

Configuration values are resolved in this order (highest priority first):

  1. Command-line flags (e.g., --listen, --backend)
  2. Environment variables (e.g., GROVE_LISTEN)
  3. grove.toml values
  4. Environment-specific defaults (based on GROVE_ENV)
  5. Built-in defaults

See Also