docs/sf/providers/aws/guide/domains.md
The Serverless Framework v4 provides built-in support for configuring custom domains for your APIs. This feature automatically handles SSL certificate creation, Route53 DNS configuration, and API Gateway domain mapping.
Acknowledgement: Big shout out to Amplify Education for creating and maintaining the original Serverless Domain Manager plugin. The custom domains feature in the Serverless Framework v4 was made possible thanks to their hard work and contributions to the community.
# serverless.yml
service: my-service
provider:
name: aws
runtime: nodejs20.x
domain: api.example.com
functions:
hello:
handler: src/hello.handler
events:
- httpApi:
path: /
method: get
serverless deploy
# serverless.yml
service: my-service
provider:
name: aws
runtime: nodejs20.x
domain: api.example.com
functions:
hello:
handler: src/hello.handler
events:
- httpApi:
path: /
method: get
# serverless.yml
service: my-service
params:
dev:
domain: api.example.dev
prod:
domain: api.example.com
provider:
name: aws
runtime: nodejs20.x
domain: ${param:domain}
functions:
hello:
handler: src/hello.handler
events:
- httpApi:
path: /
method: get
# serverless.yml
service: my-service
provider:
name: aws
runtime: nodejs20.x
domains:
- api.example.com
- api-v2.example.com
functions:
hello:
handler: src/hello.handler
events:
- httpApi:
path: /
method: get
service: your-service
provider:
name: aws
runtime: nodejs20.x
domain:
name: api.example.com
basePath: v1
apiType: http
endpointType: regional
functions:
hello:
handler: src/hello.handler
events:
- httpApi:
path: /users
method: get
websocket:
handler: src/websocket.handler
events:
- websocket:
route: $connect
For basic setups, you can specify a domain as a simple string:
provider:
domain: api.example.com
For more control, use the object format:
provider:
domain:
name: api.example.com # Required: Your custom domain name
basePath: v1 # Optional: Base path for API mapping
apiType: http # Optional: API type (http, rest, websocket)
endpointType: regional # Optional: Endpoint type (regional, edge)
accessMode: strict # Optional: REST only (single-level basePath)
You can configure multiple domains for the same service:
provider:
domains:
- name: api.example.com
apiType: http
basePath: v1
- name: api-staging.example.com
apiType: http
basePath: v1
- name: websocket.example.com
apiType: websocket
Below are all available configuration options for custom domains:
| Option | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Your custom domain name (e.g., api.example.com) |
basePath | string | No | Base path for API mapping (e.g., v1, api) |
apiType | string | No | API type: http, rest, or websocket. Defaults to http. Please note that Serverless Framework Services can only have 1 of each API Type. Therefore, when you specify apiType it will be auto-mapped to the correct one. |
endpointType | string | No | Endpoint type: regional or edge. Defaults to regional |
certificateArn | string | No | ARN of existing ACM certificate. If not provided, a new certificate will be created |
certificateName | string | No | Name of existing ACM certificate to use instead of creating a new one |
createRoute53Record | boolean | No | Whether to create Route53 DNS records. Set to false for third-party registrars. Defaults to true |
createRoute53IPv6Record | boolean | No | Whether to create IPv6 (AAAA) Route53 records. Defaults to true |
hostedZoneId | string | No | Route53 hosted zone ID. If not provided, will be automatically detected |
hostedZonePrivate | boolean | No | Whether to use a private hosted zone. Defaults to false |
route53Profile | string | No | AWS profile to use for Route53 operations |
route53Region | string | No | AWS region for Route53 operations |
route53Params | object | No | Additional parameters to pass to Route53 API calls |
splitHorizonDns | boolean | No | Enable split-horizon DNS for private hosted zones |
securityPolicy | string | No | Security policy for the domain. For domain flows routed through API Gateway V2, use TLS_1_2 |
accessMode | string | No | API Gateway endpoint access mode: basic or strict (REST domains managed by API Gateway V1 only) |
tlsTruststoreUri | string | No | S3 URI of the truststore for mutual TLS authentication |
tlsTruststoreVersion | string | No | Version of the TLS truststore |
enabled | boolean/string | No | Whether the domain is enabled. Can be a boolean or a condition string |
allowPathMatching | boolean | No | Allow path-based routing for the domain |
preserveExternalPathMappings | boolean | No | Preserve existing path mappings not managed by Serverless Framework |
provider:
name: aws
runtime: nodejs20.x
domain:
name: api.example.com
basePath: v1
apiType: rest
endpointType: regional
certificateArn: arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012
createRoute53Record: true
createRoute53IPv6Record: true
hostedZoneId: Z1PA6795UKMFR9
securityPolicy: TLS_1_2
accessMode: strict
enabled: true
allowPathMatching: false
preserveExternalPathMappings: false
route53Params:
TTL: 300
Comment: 'Custom domain for API'
functions:
hello:
handler: src/hello.handler
events:
- http:
path: /users
method: get
The Serverless Framework supports different API types for custom domains:
service: my-service
provider:
domain:
name: api.example.com
apiType: http
functions:
hello:
handler: src/hello.handler
events:
- httpApi:
path: /
method: get
service: my-service
provider:
domain:
name: api.example.com
apiType: rest
functions:
hello:
handler: src/hello.handler
events:
- http:
path: /
method: get
service: my-service
provider:
domain:
name: websocket.example.com
apiType: websocket
functions:
connect:
handler: src/websocket.connect
events:
- websocket:
route: $connect
disconnect:
handler: src/websocket.disconnect
events:
- websocket:
route: $disconnect
default:
handler: src/websocket.default
events:
- websocket:
route: $default
You can configure a base path to map your API to a specific path on your domain:
service: my-service
provider:
domain:
name: api.example.com
basePath: v1
functions:
users:
handler: src/users.handler
events:
- httpApi:
path: /users
method: get
This configuration will make your API available at https://api.example.com/v1/users.
Regional endpoints are optimized for requests from the same AWS region:
provider:
domain:
name: api.example.com
endpointType: regional
Edge endpoints use CloudFront for global distribution:
provider:
domain:
name: api.example.com
endpointType: edge
For complex applications, you can configure different domains for different purposes:
service: my-service
provider:
name: aws
runtime: nodejs20.x
domains:
- name: api.example.com
apiType: http
basePath: v1
- name: websocket.example.com
apiType: websocket
- name: admin.example.com
apiType: rest
basePath: admin
functions:
# HTTP API functions
getUsers:
handler: src/users.get
events:
- httpApi:
path: /users
method: get
# WebSocket functions
connect:
handler: src/websocket.connect
events:
- websocket:
route: $connect
# REST API functions
adminPanel:
handler: src/admin.panel
events:
- http:
path: /dashboard
method: get
Keep these rules in mind when configuring domain security:
accessMode is only supported for REST domains managed through API Gateway V1.accessMode (basic or strict) requires an enhanced securityPolicy value that starts with SecurityPolicy_.accessMode is not supported for http or websocket APIs.TLS_1_2 for securityPolicy.basePath values (for example, v1/test) are managed through API Gateway V2, so the same TLS_1_2 guidance applies.securityPolicy and accessMode values. Omitted fields are left unchanged.securityPolicy reconciliation, Serverless resolves certificate context from certificateArn in config or from the existing domain before sending the update request.Your domain must have a Route53 hosted zone configured in your AWS account. The Serverless Framework will automatically:
You must own the domain and have it configured with Route53 as the DNS provider.
If your domain is registered with a third-party registrar (not Route53), you'll need to manually create and configure the SSL certificate and DNS records.
Use the certificate ARN and disable automatic Route53 record creation:
service: my-service
provider:
name: aws
runtime: nodejs20.x
domain:
name: api.example.com
certificateArn: arn:aws:acm:us-east-1:123456789012:certificate/12345678-1234-1234-1234-123456789012
createRoute53Record: false
apiType: http
endpointType: regional
functions:
hello:
handler: src/hello.handler
events:
- httpApi:
path: /
method: get
After deploying your service, you'll need to create DNS records in your registrar:
serverless deployapi for api.example.com)d-1234567890.execute-api.us-east-1.amazonaws.com)| Option | Required | Description |
|---|---|---|
certificateArn | Yes | ARN of the manually created ACM certificate |
createRoute53Record | Yes | Set to false to prevent automatic Route53 record creation |
name | Yes | Your custom domain name |
apiType | No | API type (http, rest, websocket) - defaults to http |
endpointType | No | Endpoint type (regional, edge) - defaults to regional |
basePath | No | Base path for API mapping |
accessMode | No | basic or strict (REST + single-level basePath only) |
provider:
name: aws
runtime: nodejs20.x
domains:
- name: api.example.com
certificateArn: arn:aws:acm:us-east-1:123456789012:certificate/api-cert-12345
createRoute53Record: false
apiType: http
- name: websocket.example.com
certificateArn: arn:aws:acm:us-east-1:123456789012:certificate/ws-cert-12345
createRoute53Record: false
apiType: websocket
The Serverless Framework automatically handles SSL certificate creation and validation:
When you deploy a service with custom domains, the framework will:
us-east-1 regionIf certificate validation fails:
dig or nslookupIf your domain is not accessible after deployment:
When deploying to multiple regions with the same domain: