AWS Lambda (Part 3) - Custom Domain and Valid Certificate using AWS SAM
6 min read

AWS Lambda (Part 3) - Custom Domain and Valid Certificate using AWS SAM

Deployed a Lambda function to the AWS cloud, with a custom domain and automatically provision a valid certificate using SAM and CloudFormation.


I wrote about getting started with Serverless and AWS Lambda; Part 1 - Getting Started with Serverless, and Part 2 - Local Serverless development with AWS SAM, and just wanted to expand on this a bit in one area.

You may recall that when we deployed our Lambda function to the AWS cloud, we were presented with a URL like this:

Wouldn’t it be nice if we could have a custom domain, for example, as well as a valid certificate?

This is possible, and is what I want to expand on with this post.


  • HelleWorld example
  • AWS Route 53 Hosted Zone

HelloWorld Example

Follow Part 2 - Local Serverless development with AWS SAM to get set up.

AWS Route 53 Hosted Zone

Have AWS Route 53 manage the DNS for a domain you own in order to specify how you want to route traffic for the domain and subdomains.

If the domain was purchased through AWS, the Domain’s Name Servers and a Start of Authority (SOA) record for the zone will automatically be created for the zone.

If you want AWS Route 53 as the DNS service for an existing domain you will have to add the AWS Name Servers (NS) record and a start of authority (SOA) record with you Domain provider.

For more information please see:

Once a Zone is created, obtain the Host Zone ID, either through the AWS Console or use the aws cli . This will be required in a later step.

From the AWS Console you'll find it here:

Using the AWS CLI, it will look something like this.
(Note: the cut command is required, but feel free the | cut ... if its not available)
aws route53 list-hosted-zones-by-name \
    --dns-name ${domain} \
    --query "HostedZones[].Id" \
    --output text --no-cli-pager | cut -d'/' -f3

AWS SAM Specification

The AWS SAM specification is used to define a serverless application within an AWS SAM template. These can consist of resources types, resource properties, data types, resource attributes, intrinsic functions and API Gateways.

Furthermore, the AWS SAM templates are an extension of AWS CloudFormation templates, with some additional components that make them easier to work with. For the full reference of the AWS CloudFormation templates, see AWS CloudFormation Template Reference in the AWS CloudFormation User Guide.

Updating the SAM Template

Now that we know we can use AWS CloudFormation within the SAM Template, we need to make a few changes in order for the deployment to associate a DNS record, and provision a certificate for the API Gateway endpoint and the act as the trigger to the Lambda Function.

The following section outlines the changes required to the AWS SAM template, which you’ll find in the route of the project in the template.yaml file.


First, we’ll add the Parameters section. Parameters are specified or passed to the template and referenced within the template during runtime. This allows the ability to dynamically specify values rather than having to hardcode values in the template.

We need a Fully Qualified Domain Name ( to use the Lambda function. This is essentially where the Lambda function will be triggered from.

Next we need to add the AWS Hosted Zone ID in the format "Z111111QQQQQQQ". This is the zone for the domain and is required as CloudFormation will create DNS records; firstly, a CNAME record used for performing DNS validation when generating the Certificate, and secondly, an A record used by the API Gateway.

    Type: String
    Description: Fully qualified domain name ( to use for the Lambda function.
    Type: String
    Description: AWS Hosted Zone ID in the format "Z111111QQQQQQQ".
    Default: none


Two additional resources are required:

  • The GenerateCertificate resource which will define the properties for the certificate we require to be generated.
  • The Rest API Gateway which was essentially created implicitly when it was defined as part of the HelloWorldFunction resource. However, because we want to explicitly specify some properties a RestApiGateway resource is required. We can now explicitly define the properties for the API Gateway to make use of the generated certificate as well as the FQDN.

These resources can be added above the already present HelloWorldFunction.

  GenerateCertificate: # Creates a valid certificate for the HTTP API endpoint under the custom domain 
    Type: AWS::CertificateManager::Certificate
      DomainName: !Ref FQDN
      ValidationMethod: DNS
      - DomainName: !Ref FQDN
        HostedZoneId: !Ref ZoneId

  RestApiGateway: # Creates a HTTP API endpoint under the custom domain
    Type: AWS::Serverless::Api
      StageName: Prod
        DomainName: !Ref FQDN
        CertificateArn: !Ref GenerateCertificate
          HostedZoneId: !Ref ZoneId

    Type: AWS::Serverless::Function
      # ......

Two more changes are required for the HelloWorldFunction, specifically for the HelloWorld event’s properties:

  • Firstly, add a property RestApiId. This is the reference to the Rest API Gateway ID which is created by the RestApiGateway resource that we specified. It is useful in the way that we can reference other created resources from within the same template. This is the CloudFormation magic 🧙‍♂️.
  • Secondly, update the path by removing the hello from the URI. This is really just for demonstrative purposes. Feel free to leave it as is or update to something else.
    Type: AWS::CertificateManager::Certificate
      # .....

    Type: AWS::Serverless::Api
      # .....

    Type: AWS::Serverless::Function
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
        - x86_64
          Type: Api
            RestApiId: !Ref RestApiGateway # Add the RestApiId property
            Path: /                        # Update the path 
            Method: get


Lastly, now that we have a fully qualified domain name to access the API Gateway, the value being returned for where the API Gateway endpoint can be accessed should be updated.

NOTE: if you used a different Path: in the HelloWorldFunction properties, be sure to add it to the updated value.

  # .....
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${FQDN}/" # Updated to the FQDN
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

Deploy Changes

Now that we have made the changes it is as simple as running sam deploy with the --guided flag. The --guided flag is needed as we need to specify the parameters; FQDN and the ZoneID. But for the rest, it is exactly the same as before.

Keep in mind that the deploy takes somewhat longer because the Certificate creation requires DNS validation which takes some time to prepare and process.

Here is the full workflow of the deploy:


The output will now contain the FQDN we specified during deploy, and if the deployment was successful we'll be able to access our function using the ULR in the output.

Accessing the custom URL should now return the response from the function as well as over a secure connection using a valid certificate for the FQDN.


Same as before, to remove the stack from your AWS account, run the sam delete command.

I have noticed that the CNAME record which is created to do the DNS validation for the certificate is not removed and you would have to manually removed the record from the Route 53 Host Zone.

That should do it for now,

If you enjoyed the post, please consider to subscribe so that you receive future content in your inbox :)

Psssst, worried about sharing your email address and would rather want to hide it? Consider using a service I created to help with that:

Also, if you have any questions, comments, or suggestions please feel free to Contact Me.