Solid Start

Deploy Solid Start on AWS

The SolidJS meta-framework for building full-stack web applications.

start.solidjs.com

Deploy your Solid Start applications to AWS using Thunder. Choose the pattern that fits your app’s needs.

Available Patterns

Prerequisites

Getting Started

Create Project

Scaffold a new Solid Start project using your preferred package manager. This sets up the project structure, installs dependencies, and prepares you for development.

Terminal window
bunx create-solid@latest my-solid-app
cd my-solid-app

Install Thunder

Add Thunder as a development dependency. It provides the CDK constructs you’ll use to define your AWS infrastructure.

Terminal window
bun add @thunder-so/thunder --development

Solid Start Static Site Deployment

Deploy a fully pre-rendered Solid Start site to S3 with CloudFront as the CDN. Every page is generated at build time and served as static files — no server required.

Configure

Solid Start uses Nitro as its server engine. Set the preset to static to pre-render all routes at build time and output them to dist/.

app.config.ts
import { defineConfig } from '@solidjs/start/config';
export default defineConfig({
server: { preset: 'static' },
});

Stack

The Static construct provisions an S3 bucket, a CloudFront distribution, and optionally a Route53 DNS record.

stack/prod.ts
import { Cdk, Static, type StaticProps } from '@thunder-so/thunder';
const config: StaticProps = {
env: { account: 'YOUR_ACCOUNT_ID', region: 'us-east-1' },
application: 'myapp',
service: 'web',
environment: 'prod',
rootDir: '.',
outputDir: 'dist',
};
new Static(new Cdk.App(), `${config.application}-${config.service}-${config.environment}-stack`, config);

Deploy

Build your app first to generate the static files, then deploy with CDK. CDK uploads the files to S3 and provisions the CloudFront distribution.

Terminal window
bun run build
npx cdk deploy --app "bunx tsx stack/prod.ts" --profile default

After deployment, CDK outputs a CloudFront URL where your static site is live.


Solid Start Containerized Deployment with Fargate

Run your Solid Start app as a Node.js server inside a Docker container on ECS Fargate. Traffic is routed through an Application Load Balancer. This pattern supports full SSR, API routes, and any server-side logic.

Configure for Node Server

Set the Nitro preset to node-server so the build output is a standard Node.js HTTP server that can run inside a container. The output will be placed in .output/.

app.config.ts
import { defineConfig } from '@solidjs/start/config';
export default defineConfig({
server: { preset: 'node-server' },
});

Stack

The Fargate construct creates an ECS cluster, a Fargate task definition, and an Application Load Balancer.

stack/prod.ts
import { Cdk, Fargate, type FargateProps } from '@thunder-so/thunder';
const config: FargateProps = {
env: { account: 'YOUR_ACCOUNT_ID', region: 'us-east-1' },
application: 'myapp',
service: 'web',
environment: 'prod',
rootDir: '.',
serviceProps: {
dockerFile: 'Dockerfile',
architecture: Cdk.aws_ecs.CpuArchitecture.ARM64,
cpu: 512,
memorySize: 1024,
port: 3000,
desiredCount: 1,
healthCheckPath: '/',
},
};
new Fargate(new Cdk.App(), `${config.application}-${config.service}-${config.environment}-stack`, config);

Dockerfile

Create a Dockerfile in your project root. The multi-stage build keeps the final image lean by separating the build environment from the runtime.

Dockerfile
FROM oven/bun:latest AS builder
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
FROM oven/bun:latest AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV HOST=0.0.0.0
ENV PORT=3000
COPY --from=builder /app/.output ./
EXPOSE 3000
CMD ["bun", "run", "server/index.mjs"]

Environment Variables and Secrets

Runtime environment variables are injected into the Fargate task at deploy time. For sensitive values, store them in AWS Secrets Manager and reference them by ARN — Thunder fetches and injects them automatically.

stack/prod.ts
const config: FargateProps = {
// ...
serviceProps: {
// ...
variables: [
{ NODE_ENV: 'production' },
],
secrets: [
{
key: 'DATABASE_URL',
resource: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:/myapp/DATABASE_URL-abc123',
},
],
},
};

Deploy

CDK builds the Docker image, pushes it to ECR, and deploys it to Fargate. No manual Docker commands needed.

Terminal window
npx cdk deploy --app "bunx tsx stack/prod.ts" --profile default

After deployment, CDK outputs the Load Balancer DNS for your application.


Solid Start Serverless Fullstack Deployment

Deploy Solid Start with SSR using AWS Lambda for server-side rendering, S3 for static assets, and CloudFront to unify both behind a single domain. This pattern scales to zero and charges only for actual requests.

Configure Solid Start for AWS Lambda

Solid Start uses Nitro as its server engine. Set the aws-lambda preset to tell Nitro to output a Lambda-compatible handler instead of a Node.js HTTP server.

app.config.ts
import { defineConfig } from '@solidjs/start/config';
export default defineConfig({
server: { preset: 'aws-lambda' },
});

The build will produce .output/server/ (Lambda handler) and .output/public/ (static assets for S3).

Stack (Zip mode)

The SolidStart construct wires up Lambda, API Gateway, S3, and CloudFront automatically. By default, Thunder packages your Lambda handler as a Zip deployment — the fastest option for most apps.

stack/prod.ts
import { Cdk, SolidStart, type SolidStartProps } from '@thunder-so/thunder';
const config: SolidStartProps = {
env: { account: 'YOUR_ACCOUNT_ID', region: 'us-east-1' },
application: 'myapp',
service: 'web',
environment: 'prod',
rootDir: '.',
};
new SolidStart(new Cdk.App(), `${config.application}-${config.service}-${config.environment}-stack`, config);

Container Mode

Zip deployments have a 250 MB unzipped size limit. If your app has large dependencies — native modules, ML libraries, or heavy assets — switch to container mode. Thunder builds a Docker image, pushes it to ECR, and deploys it as a container Lambda, which supports up to 10 GB.

Stack (Container mode)

Add dockerFile to serverProps to enable container mode.

stack/prod.ts
const config: SolidStartProps = {
// ...
serverProps: {
dockerFile: 'Dockerfile',
memorySize: 2048,
},
};

Dockerfile

Dockerfile
FROM public.ecr.aws/lambda/nodejs:22
# Copy all lambda files
COPY . ./
CMD ["index.handler"]

Environment Variables and Secrets

Runtime environment variables are injected into the Lambda function at deploy time. For sensitive values, store them in AWS Secrets Manager and reference them by ARN — Thunder fetches and injects them automatically.

stack/prod.ts
const config: SolidStartProps = {
// ...
serverProps: {
variables: [
{ NODE_ENV: 'production' },
],
secrets: [
{
key: 'DATABASE_URL',
resource: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:/myapp/DATABASE_URL-abc123',
},
],
},
};

Deploy

Build your Solid Start app first to generate the Lambda handler and static assets, then deploy with CDK.

Terminal window
bun run build
npx cdk deploy --app "bunx tsx stack/prod.ts" --profile default

After deployment, CDK outputs a CloudFront URL that serves both your SSR responses and static assets.