Configuration
GoForj uses two main configuration layers: project configuration and runtime environment configuration.
.goforj.yml describes what the App is and how local development should run. .env files describe how the App behaves when it starts.
When To Change Configuration
| Question | Guidance |
|---|---|
| Use this when | You need to change generated shape, runtime behavior, drivers, resource names, ports, secrets, or deployment defaults. |
| Avoid this when | You are trying to express business behavior that belongs in services, routes, jobs, schedules, or lifecycle hooks. |
| Start with | .env for local runtime behavior and .goforj.yml for generated App shape. |
| Upgrade to | Environment-specific files, process environment, secret management, and build-time defaults or overrides for packaged deployments. |
Configuration Layers
| Layer | File or source | Purpose |
|---|---|---|
| Project configuration | .goforj.yml | Component selection, rendering, dev watchers, Wire paths, module replacements |
| Runtime environment | .env, .env.local, .env.host, process env | App name, ports, secrets, drivers, resource settings |
| Generated code | internal/*/*_gen.go, wire/wire_gen.go | Derived accessors, driver imports, provider wiring |
| Build-time options | forj build flags | Optional compiled defaults, overrides, and default launch behavior |
The important rule: change the correct layer for the behavior you want.
.goforj.yml
.goforj.yml is the render contract for the App.
It includes fields such as:
project_name: Example
module_name: example.com/example
dev:
auto_migrate: true
down_on_exit: true
wire_paths:
- wire
render:
starter_kit: none
queue_driver: redis
components:
cli: true
web_api: true
jobs: true
scheduler: true
database_mysql: trueUse .goforj.yml when you need to change the generated project shape, enabled components, local dev watchers, or module replacement behavior.
Environment Files
Runtime behavior is configured through environment variables.
The generated project includes:
.envfor the main local runtime configuration..env.localfor local overrides..env.hostfor host-specific local infrastructure settings.
The generated main.go calls the App environment loader before wire.InitializeApplication().
Common variables include:
APP_NAME=Example
APP_ENV=local
APP_DEBUG=0
APP_URL=http://localhost:3000
APP_SHUTDOWN_TIMEOUT=30s
API_HTTP_HOST=0.0.0.0
API_HTTP_PORT=3000
CACHE_DRIVER=memory
CACHE_SUPPORTED_DRIVERS=memory
STORAGE_DRIVER=local
STORAGE_SUPPORTED_DRIVERS=local
EVENTS_DRIVER=inproc
EVENTS_SUPPORTED_DRIVERS=inprocDriver Configuration
GoForj separates compile-time driver support from runtime driver selection.
*_SUPPORTED_DRIVERS controls which drivers are generated into the App at compile time.
*_DRIVER selects which supported driver is used at runtime.
For named resources, use *_<NAME>_DRIVER.
Example:
CACHE_SUPPORTED_DRIVERS=memory,redis
CACHE_DRIVER=memory
CACHE_SESSIONS_DRIVER=redisThis generates support for memory and Redis cache drivers. The default cache uses memory. The named sessions cache uses Redis.
This pattern appears across GoForj primitives:
CACHE_SUPPORTED_DRIVERS,CACHE_DRIVER,CACHE_<NAME>_DRIVERSTORAGE_SUPPORTED_DRIVERS,STORAGE_DRIVER,STORAGE_<NAME>_DRIVERQUEUE_SUPPORTED_DRIVERS,QUEUE_DRIVER,QUEUE_<NAME>_DRIVEREVENTS_SUPPORTED_DRIVERS,EVENTS_DRIVER,EVENTS_<NAME>_DRIVERDB_SUPPORTED_DRIVERS,DB_DRIVER
Regenerate After Driver Changes
Changing supported drivers can change imports, managers, and generated accessors.
The normal path is:
forj buildforj build runs generation, Wire, API indexing, and go build.
Dev Loop
During local development, forj dev normally runs the generated build watcher for you, so saving the relevant configuration or source changes will flow through forj build.
Use focused generation only when you intentionally want to refresh one generated surface without running the full build:
forj generate --cache
forj generate --storage
forj generate --queue
forj generate --events
forj generate --dbLocal-First Defaults
Generated Apps prefer local defaults first:
- memory cache
- local storage
- in-process events
- local or compose-backed databases
- local queue drivers when selected
Production deployments can swap drivers through environment and providers without rewriting application business logic.
Named Resources
Named resources are generated from scoped environment variables.
For storage:
STORAGE_SUPPORTED_DRIVERS=local,s3
STORAGE_DRIVER=local
STORAGE_PUBLIC_DRIVER=local
STORAGE_UPLOADS_DRIVER=s3
STORAGE_UPLOADS_BUCKET=my-app-uploads
STORAGE_UPLOADS_REGION=us-east-1The generated App can expose named accessors such as:
app.Storage().Public()
app.Storage().Uploads()Named generated accessors represent generated configuration invariants. If the current environment and generated code are out of sync, those accessors fail fast instead of silently returning a missing dependency.
Build-Time Environment Defaults
forj build can compile default or forced environment values into the binary:
forj build --env-defaults APP_ENV=local
forj build --env-overrides APP_ENV=productionDefaults apply only when a key is unset. Overrides force the value.
These options are useful for packaging, but most local development should use .env files and process environment variables.
Common Mistakes
Common mistakes
- Do not add a runtime driver without also including it in
*_SUPPORTED_DRIVERSwhen generated code needs that driver compiled in. - Do not edit generated managers by hand to add resources. Change environment configuration and regenerate.
- Do not put business behavior in
.goforj.yml; it is a project and development configuration file. - Do not use cache as durable business storage.
Next Steps
- Project Structure explains where generated configuration is used.
core/drivers-and-adapters.mdwill explain swappable infrastructure in more depth.- Libraries links to standalone driver matrices and package APIs.
