Skip to main content
Complete these first:

Overview

fjall add edits an application’s infrastructure.ts through the codemod engine. It writes the CDK code, typechecks the edited file, and reports the lines changed. Nothing reaches AWS until you run fjall deploy. Adding resources before the first deploy is fine. Everything you add lands on the next fjall deploy. Every add follows one shape:
fjall add never prompts. A missing <type>, --app or --name exits with a validation error rather than opening a picker. The Ink resource wizard still exists, but its only route in is the “add your first resource” hand-off shown after fjall create app for a custom-tier application.
There is no colon syntax. fjall add database:Aurora is invalid. The database variant is a property: --type Aurora.

Property flags are schema keys

Property flag names are the resource schema’s own camelCase keys, used verbatim. --databaseName is correct, --database-name is not. Four parsing rules apply:
  1. Each flag consumes the next token as its value. A trailing flag with no value is refused.
  2. There are no value-less booleans. Pass an explicit value, such as --deletionProtection true.
  3. Duplicate flags are refused, so a typo surfaces instead of silently overwriting.
  4. A value starting with { or [ must parse as JSON.
A wrong key is refused with the nearest match and the full permitted list, so fjall add database --bogus x is a safe way to discover the vocabulary.

Options

--preset and --tier are selectors. They expand into the same explicit properties you could type by hand, and neither name reaches the emitted statement. The two cannot be combined, --tier on a database also needs --type, and explicit property flags win over the preset.

Required properties

The add contract keeps every non-optional schema key required. A missing key is refused before the file is touched, and the error names every absent key at once. Run fjall add database --app api --name Analytics with neither and the refusal is explicit:
--tier does not supply these. A tier preset carries tuning (instance class, reader count, backup schedule), not the identity of the resource. Full per-type contract, including vpc-peer, cross-plan-connection and buildkite: fjall add.

Add a database

Pick the engine and topology with --type, and name the logical database with --databaseName:
DynamoDB is not a database type. fjall add database --type DynamoDB is refused. DynamoDB tables come from the OpenNext pattern, not from fjall add database.

Multiple databases

An application can hold several databases. Give each a distinct name:

Start from a tier preset

--tier expands that tier’s preset for the chosen --type. Explicit flags override it:

Add storage

An S3 bucket needs nothing beyond a name:
--preset expands a starting configuration:

Add compute

compute covers Lambda functions, ECS clusters and EC2 workloads. Both required properties must be present:
--tier is refused on compute. A compute tier preset is keyed by compute type and carries scaffold placeholders that only fjall apps create --tier fills in.

Wire a new Lambda to a sibling resource

Connection keys resolve sibling resource names to their bindings and write the wiring the construct reads:
--connectedStorage and --connectedMessaging work the same way. Only database wiring is gated on --needsConnection true.
Connection keys apply to a new Lambda only. On an ECS cluster the codemod refuses, because ECS wires connections per service. On an existing compute fjall modify refuses, because the keys rebuild environment, secretsImport and connections wholesale. Both cases are authored in infrastructure.ts directly.

Add a CDN

A CloudFront distribution needs an origin that already exists in the same infrastructure.ts. Add the origin first:
--defaultOriginRef names a storage bucket or an ECS compute declared in the same file.

What Fjall wires for you

The codemod writes the connection props. The CDK constructs turn them into real AWS wiring on the next deploy.

Connection environment variables

The first connection of a kind carries no suffix. The second gets _2, the third _3:

Review and deploy

Adding a resource only edits a file. Check the edit, then provision it.
1

Confirm the resource landed

2

Typecheck and synthesise

--deep runs tsc --noEmit over the edited file. Adding --synth also builds the CloudFormation template locally, with no AWS lookups.
3

Deploy

At a terminal, fjall deploy prints a resource-level plan and asks for approval before anything changes:
The prompt defaults to No. A deploy with nothing to change stops before the gate:
--skip-confirmation and --auto-approve drop the prompt for scripted runs. In CI, pass --plan to stop before any mutation (exit 0 for no changes, 2 for changes pending approval, 1 for an error). Wrong resource? fjall undo --app api restores the most recent .bak sidecar of infrastructure.ts.

Scripting fjall add

fjall add is already safe in a pipeline, because it never prompts. --non-interactive only forces plain output for CI logs. What makes a scripted add succeed is supplying every required property:

Worked example

Build an API application with a bucket, a Lambda and a database, then deploy it:

All resource types

<type> is one of these twelve exact values:
fjall add messaging writes an SQS queue. SNS topics and EventBridge buses are authored through MessagingFactory in infrastructure.ts rather than through fjall add.

Next Steps

fjall add reference

Every flag, property and per-type add contract.

Deploy Application

Provision the updated infrastructure on AWS.

fjall modify

Change the properties of a resource you already added.

fjall remove

Remove a resource from infrastructure.ts.

fjall validate

Typecheck and synthesise before deploying.

Destructive Changes

What happens when a change replaces or destroys a resource.