chalice-http-toolkit enables a Flask like website building experience using Chalice, AWS Lambda, API Gateway & CloudFront. It does this by bolting on Jinja2 templates, and CloudFront cache management layer.


Base installation via pip:

pip install chalice-http-toolkit

The above command only installs the base dependancies, there is also an additional extra_requires directive shown below that installs packages which would normally push your Lambda package over the 250MB limit.

For local testing the rest of the dependancies can be installed via:

pip install chalice-http-toolkit[layered]

For deployments to AWS Lambda the following layers should be used:


OR run

$ chalice-http-toolkit layers -r us-east-1 # Returns the latest compatible layer versions

Quick setup

challice-http-toolkit now comes with a CLI utility to quicky create a project, usage is as follows:

chalice-http-toolkit setup -n myapp -p . -e magic -r us-east-1

The above script does the following:

  1. Creates your, with handlers for index, static content, 404 and a event to keep the Lambda function warm.

  2. Creates directory structure for templates, static content, chalice libraries.

  3. Sets up Chalice layers (Pillow and Jinja2) which are required chalice-http-toolkit.

  4. If -e magic is provided, then magic binaries are included in chalicelib/libs directory. This is required because Lambda instances dont include these binaries so magic wont work without it.

The latest layers can be fetched using the following command:

chalice-http-toolkit layers -r us-east-1

Currently only Python 3.8 is supported for chalice-http-toolkit, this is because we would need to extract binaries for magic from different AWS Linux versions with varying Python versions and also build Pillow and Jinja2 layers for different Python versions.

Chalice config.json

A basic Chalice config.json is defined below which has two stages, dev is meant for local testing and prod is the stage which gets deployed to AWS Lambda. The STAGE environment variable must be defined for local testing to work around some differences between AWS API Gateway behaviour vs the way locally served API works.

  "version": "2.0",
  "app_name": "example",
  "stages": {
    "dev": {
      "api_gateway_stage": "dev",
      "lambda_timeout": 60,
      "lambda_memory_size": 64,
      "environment_variables": {
        "STAGE": "dev"
    "prod": {
      "api_gateway_stage": "prod",
      "layers": ["arn:aws:lambda:us-east-2:770693421928:layer:Klayers-python38-jinja2:2",
      "lambda_timeout": 60,
      "lambda_memory_size": 64,
      "environment_variables": {
        "STAGE": "prod"

Project Structure

Templates and static content needs to be placed in the chalicelib directory because that is where additional content is packaged into the deployment by Chalice.


Placing CloudFront in front of a chalice-http-toolkit website is not required, but if your website is popular it probably starts to make sense given that every invocation ends up costing more then it would for CloudFront to server the website.


class chalice_http_toolkit.content.ContentManager[source]

This class is designed to support:

  • serving static content (such as Javascript/CSS). Although these might be better served by S3 depending on scale.

  • rendering Jinja2 templates

  • support generating 304 redirects

  • support returning JSON Responses

  • serving assets

  • converting images based on the accepts header in a request

  • cleaner handling of binary content

Every chalice-http-toolkit app requires a ContentManager be created, usually right after the Chalice app is created.


class chalice_http_toolkit.cloudfront.CloudFront[source]

This class is designed to support:

  • caching static content by modifed dates

  • caching Jinja2 templates by hashing dependancies (ie arguments and child templates) without rendering.

  • caching assets

Using this module is optional, but it is best practice.


There are a few differences between locally testing & a deployed instance of a Chalice website. They are detailed below.

Binary Content

Due to the way API Gateway handles binary content, the binary content is Base64 encoded in the absence of an Accepts header in the request. This restriction does not apply for local testing.

Request & Reponse Limits

API Gateway has a request & response filesize limit of 10MB. This restriction does not apply for local testing.

Cold Starts

Chalice based websites are vulnerable to the Lambda Coldstart problem. A cold start happens when you execute an inactive function. The delay comes from AWS provisioning your selected runtime container and then running your function. Functions stay ‘warm’ for approximately 5 minutes, which means they respond to requests much quicker. After this period of time, the contianer is dropped by AWS and a cold start needs to happen.