Configuration

Every app needs settings: a database DSN, secret keys, feature flags, the current environment. Fast keeps this simple with a small set of env() helpers that read typed values, and a strong recommendation about where not to put your secrets.

Reading environment values

The env() helper reads a value with an optional default:

$dsn = env('DB_DSN', 'sqlite::memory:');
$debug = env('APP_DEBUG');

For safety and convenience, there are typed variants that coerce and validate the value for you, so you are not passing strings where you meant booleans or ints:

$secure   = env_bool('LOCAL_HTTP', false);
$workers  = env_int('WORKERS', 4);
$key      = env_string('APP_KEY', '');

env_bool() understands the usual truthy spellings, env_int() gives you a real integer, and env_string() guarantees a string. Each takes a default that is used when the variable is absent.

Using config at boot

Because you register everything before serve(), configuration naturally flows into your use_* calls at the top of your server file:

require __DIR__ . '/bootstrap.php';

use Fast\Database\Config as DbConfig;
use Fast\Session\SessionConfig;

use_database(new DbConfig(
	dsn: env_string('DB_DSN'),
	username: env_string('DB_USER'),
	password: env_string('DB_PASSWORD'),
));

use_session(new SessionConfig(
	key: env_string('APP_KEY'),
	secure: !env_bool('LOCAL_HTTP'),
));

serve(port: env_int('PORT', 8080), workers: env_int('WORKERS', 4));

This reads top to bottom: pull typed values from the environment, feed them into the subsystem configs, and start the server.

Where to keep secrets

A common pattern is a PHP file that returns your environment values, something like .env.php. Wherever you keep them, one rule is non-negotiable:

Never place your .env.php, keys, or any secret inside a directory you serve as static files. If a secret sits under a files() root, it is one URL away from the public internet. Keep configuration well outside any static mount, and never commit production secrets to your repository.

Keys and rotation

Secret keys, like your session and component keys, deserve special care. Generate them once with the appropriate helper (for sessions, SessionConfig::generateKey()), store them securely, and reuse the same value across boots.

A fresh key on every boot invalidates every existing session and every live component's carried state. Generate once, store it, and load it from configuration. When you do need to rotate, Fast supports an id => key map so a new key can seal new tokens while older keys keep decrypting sessions that have not yet expired.

Server configuration

Beyond your app's own settings, serve() exposes the server's operational knobs directly as named arguments: workers, maxRequests, maxMemory, idleTimeout, and several timeouts. These are worth understanding on their own, and they are covered in Server Runtimes and Workers & Lifecycle.

That wraps up the utilities. Next we go under the hood into how Fast actually runs your server, starting with Server Runtimes.