Skip to main content

Overview

StorageFactory creates S3 bucket resources with type-safe configurations. Every bucket comes from the single S3Bucket class. Different property combinations control the behaviour (private, website hosting, public read access).
For databases (Aurora, RDS, DynamoDB), use the DatabaseFactory instead.

Basic Usage

Bucket Configurations

Private Bucket (Default)

Standard bucket with no public access. Best for application assets, uploads and caches:
Versioning follows the application’s backup tier. A bucket in an application created with App.getApp(name, { backup: { tier: "resilient" } }) (or "enterprise") is versioned by default, with a 30-day noncurrent-version expiry rule. A standard application, or one with no backup tier, leaves versioning off. Set versioned to override the tier in either direction, or backupVaultTier to give one bucket a different tier from the application. Features:
  • Private by default (block public access set to BLOCK_ALL)
  • Versioning driven by the backup tier
  • Optional encryption (AES256 or KMS)

Website Hosting Bucket

Configure a bucket for static website hosting with the websiteHosting property:
Features:
  • Static website hosting enabled
  • Configurable index and error documents (errorDocument defaults to error.html)
  • CORS support
Setting websiteHosting makes the bucket publicly readable. The S3 website endpoint has no other access path, so the factory applies the same public-read policy it applies for publicReadAccess: true. For a private origin behind CloudFront, use the CDN Factory instead.

Public Read Access Bucket

Grant public read access to all objects with the publicReadAccess property:
Features:
  • All objects publicly readable through a bucket policy
  • Best for CDN origin buckets
  • Optional versioning and encryption

Removal Policy

removalPolicy decides whether a bucket survives stack teardown. It is the highest-consequence property on the factory.
A DESTROY bucket carries the fjall:sdk-pre-empty tag, so fjall destroy empties it before CloudFormation deletes the stack. Without that tag, a non-empty bucket blocks the delete.

Configuration Parameters

Common Patterns

Media Uploads

Store user-uploaded media. A resilient or enterprise application versions the bucket through its tier. versioned: true pins versioning on whatever the application tier is:

Static Assets with Deployment

Upload static assets during CDK deployment:

ISR Cache Bucket

Cache bucket for Next.js ISR:

Website with CORS

Website bucket with CORS for API requests:
allowedMethods accepts GET, PUT, POST, DELETE and HEAD. Any other value fails synth.

CDN Origin Bucket

Place a bucket in the CDN stack to avoid circular dependencies:

KMS Encryption

KMS buckets turn on S3 Bucket Keys by default, which cuts per-object KMS request charges. Pass bucketKeyEnabled: false to opt out. Omitting kmsKeyArn falls back to the AWS-managed key and raises a synth warning.

Bucket Policy Statements

Append statements to the bucket’s resource policy. Principals are either "*" or an IAM ARN:
The TLS-only deny statement is applied separately on every bucket. Do not add it here.

Deploying Assets After Construction

The constructor deployment property uploads assets but cannot invalidate a CloudFront cache, because the distribution does not exist yet when the bucket is built. Call deployAssets(config, distribution?) after the CDN to get both:
Passing the distribution invalidates /* after upload, so new assets serve immediately instead of waiting out the cache TTL. A bucket deploys one asset set. Calling deployAssets when a deployment already exists (from the constructor deployment property or a prior call) throws rather than stacking a second BucketDeployment whose prune semantics would fight the first.

Accessing Bucket Information

The bucket ARN and name are also emitted as CloudFormation outputs, exported as <stackName><id>BucketArn and <stackName><id>BucketName.

Connecting to Compute Resources

Pass the storage construct in a compute resource’s connections array. Fjall grants the IAM policy. Storage connections default to readWrite:
On ECS, connections sits on the service, not on the compute props. On Lambda it sits at the top level. connections handles IAM only. Pass the bucket name through environment when the application code needs it at runtime.

Granting Access

Grant access directly to any IAM grantable when connections is not the right fit:
grantPublicAccess writes a bucket policy, so it works only on a bucket created with publicReadAccess: true or websiteHosting. A private bucket blocks public policies.

Event Notifications

Security

Every bucket gets these without configuration:
  • TLS-only access: a deny statement rejects non-HTTPS requests
  • Encryption: SSE-S3 applies by default. Set encryption to pin AES256 or KMS
  • Multipart hygiene: incomplete multipart uploads abort after 7 days, so abandoned parts stop accruing storage cost
  • IAM policies: least-privilege grants from connections and the grant* methods

Block Public Access

A private bucket asserts BLOCK_ALL in the template rather than relying on the account default, so a manually loosened bucket is healed on the next deploy. Setting publicReadAccess: true or websiteHosting opens the two policy halves (blockPublicPolicy and restrictPublicBuckets off) and keeps the two ACL halves closed (blockPublicAcls and ignorePublicAcls on). Public access is bucket-policy-based, because ACLs are disabled on modern buckets.

Best Practices

  1. Keep buckets private by default - Set publicReadAccess or websiteHosting only when a public endpoint is the requirement
  2. Choose a backup tier that matches the data’s recovery needs - Override versioned or backupVaultTier only for a single-bucket exception
  3. Set removalPolicy: "RETAIN" on any non-production bucket holding data you cannot re-create
  4. Use KMS encryption for regulated or customer-sensitive data, and leave bucketKeyEnabled on
  5. Use deployment or deployAssets for static assets instead of a manual S3 sync
  6. Set stackPlacement to "cdn" when the bucket is a CloudFront origin

Next Steps

CDN Factory

Front a bucket with CloudFront

Compute Factory

Deploy Lambda and ECS compute resources

Database Factory

Create Aurora, RDS and DynamoDB databases

Static Site Pattern

Deploy a static site with bucket, CDN and DNS