Skip to content

Configuration

VentureKit uses a layered configuration system that separates concerns cleanly:

LayerFilePurposeChanges per environment?
Baseconfig/base.tsProject identityNo
Securityconfig/security.tsOAuth scopes, app clientsNo
Infrastructurevk.config.ts (flat fields)Databases, storage, queuesSizing overrides per env
Environmentconfig/dev.ts, config/prod.tsResource sizing, scalingYes

Shared infrastructure definitions (names, types, purposes) live directly on vk.config.ts. Per-environment overrides (sizing, behavior) go in config/dev.ts and config/prod.ts. Everything is merged at deploy time into a single ResolvedConfig with no undefined values.

Project identity that never changes between environments:

config/base.ts
import type { BaseConfig } from '@venturekit/core';
export const base: BaseConfig = {
name: 'my-api', // Lowercase, no spaces, used in resource naming
displayName: 'My API', // Display name for UI/logs
region: 'eu-west-1', // AWS region (same for all environments)
};

Validation rules:

  • name must start with a lowercase letter, contain only [a-z0-9-], max 32 characters
  • displayName is required
  • region must be a valid AWS region format (e.g., eu-west-1)

Authentication and authorization settings, shared across all environments:

config/security.ts
import type { SecurityConfig } from '@venturekit/core';
export const security: SecurityConfig = {
scopes: [
{ name: 'tasks.read', description: 'Read tasks' },
{ name: 'tasks.write', description: 'Create and update tasks' },
{ name: 'admin', description: 'Admin access' },
],
appClients: [
{
name: 'web-app',
allowedScopes: ['tasks.read', 'tasks.write'],
supportsRefreshTokens: true,
},
{
name: 'admin-app',
allowedScopes: ['tasks.read', 'tasks.write', 'admin'],
supportsRefreshTokens: true,
},
],
};

Validation rules:

  • At least one scope is required
  • At least one app client is required
  • All allowedScopes must reference defined scopes

Declarative infrastructure intents — declare what you need, not how to build it. Shared definitions go directly on defineVenture() in vk.config.ts, and per-environment overrides go in config/dev.ts / config/prod.ts:

// vk.config.ts — shared definitions (names, types, purposes)
export default defineVenture({
base,
security,
databases: [
{ id: 'main', type: 'postgres', name: 'mydb' },
],
storage: [
{ id: 'uploads', purpose: 'uploads' },
],
envs: { dev, prod },
});
// config/prod.ts — per-env overrides (sizing, behavior)
export const prod: EnvConfigInput = {
preset: 'medium',
databases: [
{ id: 'main', size: 'large', highAvailability: true, backups: true },
],
storage: [
{ id: 'uploads', cdn: true },
],
};

Overrides are matched by id and shallow-merged with the shared definitions at deploy time.

See Infrastructure Intents for all available intent types.

Resource sizing that changes per environment. Start with a preset and override as needed:

config/dev.ts
import type { EnvConfigInput } from '@venturekit/core';
export const dev: EnvConfigInput = {
preset: 'free',
api: {
cors: {
allowOrigins: ['http://localhost:3000', 'http://localhost:5173'],
},
},
};
config/prod.ts
import type { EnvConfigInput } from '@venturekit/core';
export const prod: EnvConfigInput = {
preset: 'medium',
api: {
cors: {
allowOrigins: ['https://app.example.com'],
allowCredentials: true,
},
},
};
Lambda

memoryMb (128–10240), timeoutSec (1–900), vpcEnabled, logRetentionDays, tracingEnabled, architecture (arm64 | x86_64), runtime, IAM policies.

API Gateway

throttleRateLimit, throttleBurstLimit, cors (origins, methods, headers, credentials), customDomain (domain name, certificate ARN).

VPC

maxAzs (1–3), natGateways, subnets, security group rules.

Observability

alarmsEnabled, tracingEnabled, detailedMetricsEnabled, log group config, metrics config.

WebSocket

enabled, routeSelectionExpression, idleTimeoutSec, throttleRateLimit, throttleBurstLimit.

The vk.config.ts at your project root wires everything together:

import { defineVenture } from '@venturekit/infra';
import { base } from './config/base';
import { security } from './config/security';
import { dev } from './config/dev';
import { prod } from './config/prod';
export default defineVenture({
base,
security,
databases: [
{ id: 'main', type: 'postgres', name: 'app' },
],
storage: [
{ id: 'uploads', purpose: 'uploads' },
],
envs: { dev, prod },
});

Shared infrastructure definitions live directly on defineVenture(). Environment configs (config/dev.ts, config/prod.ts) override only what differs per environment.

At deploy time, VentureKit resolves the full configuration:

  1. Select the environment from VENTURE_STAGE (defaults to dev)
  2. Look up the matching preset (if specified)
  3. Merge preset defaults with explicit overrides
  4. Combine base + security + resolved environment into ResolvedConfig
  5. Validate the entire configuration
import { resolveConfig } from '@venturekit/core';
const config = resolveConfig(base, security, 'prod', prodInput);
// Returns a ResolvedConfig with all fields defined — no undefined values

The VENTURE_STAGE environment variable controls which config is used:

Terminal window
vk dev # Uses dev config
VENTURE_STAGE=prod vk deploy # Uses prod config