OpenNext Configuration
OpenNext compiles Next.js for deployment on AWS Lambda. This document covers the configuration and build process.
Overview
OpenNext transforms Next.js output for AWS:
- Lambda functions for SSR and API routes
- S3 for static assets
- DynamoDB/S3 for ISR cache
- CloudFront for CDN
Configuration File
open-next.config.ts:
import type { OpenNextConfig } from '@opennextjs/aws/types/open-next';
const config: OpenNextConfig = {
default: {
override: {
tagCache: 'dynamodb-lite',
incrementalCache: 's3-lite',
queue: 'sqs-lite',
},
},
functions: {
chat: {
patterns: ['/api/chat', '/api/chat/*'],
override: {
wrapper: 'aws-lambda-streaming',
},
},
},
};
export default config;
Build Process
pnpm build:web
# or
pnpm dlx @opennextjs/aws@latest build
Output Structure
.open-next/
├── open-next.output.json # Build manifest
├── server-function/ # Lambda@Edge server
│ ├── index.mjs
│ └── node_modules/
├── image-optimization-function/
│ ├── index.mjs
│ └── sharp/ # Native image processing
├── cache/
│ └── __fetch/ # Data cache
├── dynamodb-provider/ # Cache initialization
├── revalidation-function/ # ISR worker
└── assets/ # Static files
├── _next/
│ ├── static/ # Immutable chunks
│ └── data/ # Route data
└── ... # Public files
Cache Configuration
Incremental Cache (S3)
ISR page cache stored in S3:
s3://assets-bucket/_cache/
├── __fetch/ # Data cache
└── pages/ # Page cache
Tag Cache (DynamoDB)
Maps cache tags to paths for revalidation:
| tag | path | revalidatedAt |
|-----|------|---------------|
| posts | /blog | 1699999999 |
| post:my-slug | /blog/my-slug | 1699999999 |
Revalidation Queue (SQS)
FIFO queue for processing revalidation requests:
{
"tag": "posts",
"paths": ["/blog", "/api/posts"]
}
Function Configuration
Default (Lambda@Edge)
All routes except explicit overrides:
- ISR pages
- API routes
- Dynamic routes
Chat Function
Separate regional Lambda with streaming:
functions: {
chat: {
patterns: ['/api/chat', '/api/chat/*'],
override: {
wrapper: 'aws-lambda-streaming',
},
},
}
Required because:
- Lambda@Edge doesn't support streaming
- Function URLs enable response streaming
- Regional deployment allows longer timeouts
Next.js Configuration
next.config.mjs settings for OpenNext:
const nextConfig = {
output: 'standalone',
outputFileTracingIncludes: {
'/**': [
'./generated/**/*',
'./chat.config.yml',
'./node_modules/react/**/*',
'./node_modules/react-dom/**/*',
],
},
experimental: {
serverActions: {
bodySizeLimit: '2mb',
},
},
};
Output Tracing
Files included in Lambda bundles:
generated/- Chat embeddingschat.config.yml- Chat configuration- React runtime for Server Components
Environment Variables
At build time:
# GitHub data for static generation
GH_TOKEN=...
PORTFOLIO_GIST_ID=...
# AWS resources (if available)
POSTS_TABLE=...
CONTENT_BUCKET=...
At runtime (via Secrets Manager or origin headers):
OPENAI_API_KEY=...
NEXTAUTH_SECRET=...
# ... other secrets
CDK Integration
The CDK stack reads open-next.output.json:
const openNextOutput = JSON.parse(
fs.readFileSync('.open-next/open-next.output.json', 'utf-8')
);
// Create Lambda functions from output
for (const [name, config] of Object.entries(openNextOutput.origins)) {
if (config.type === 'function') {
createLambdaFunction(name, config);
}
}
// Configure CloudFront behaviors
for (const behavior of openNextOutput.behaviors) {
createBehavior(behavior);
}
Troubleshooting
Build Fails with Missing Modules
Ensure all dependencies are properly traced:
// next.config.mjs
outputFileTracingIncludes: {
'/api/**': ['./node_modules/some-package/**/*'],
}
Lambda Bundle Too Large
Check bundle size and optimize:
du -sh .open-next/server-function/
Solutions:
- Exclude dev dependencies
- Use dynamic imports
- Check for duplicate modules
ISR Not Working
Verify cache configuration:
- Check DynamoDB tag cache table exists
- Verify S3 cache bucket permissions
- Check revalidation queue is processing
Related Documentation
- Infrastructure - AWS resources
- Deployment - Deploy process
