Build a Python Microservice with Amazon Web Services Lambda & API Gateway

Post to Twitter

I think in many ways AWS (Amazon Web Services) is a game changer for the entire “cloud”. Many companies base all or some of their infrastructure on AWS. Today I want to kick off an AWS Lambda tutorial from a Python developer’s perspective. Since the past year the Python code I write my articles have been done in Python 3.x however today’s article is an exception since the actual hosted Lambda Python code has to be Python 2.7 since that is what AWS Lambda currently only supports (Jan. 2016). Regardless of having to use Python 2.7.x AWS Lambda is very cool to work with and has a lot of potential to make some very useful services.

Amazon Web Services – Lambda (Python) & API Gateway

AWS API Gateway as the main webpage states: “Amazon API Gateway is a fully managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale”. I will use this to create a simple Web based API for the example “Microservice” project.

Lambda is an exciting service AWS offers. Python support was added to Lambda at the AWS re:Invent 2015 event. When you log into the AWS console its actually staggering to see the amount of services AWS supports – they currently dwarf any other cloud service provider in this regard.

AWS Services

Note: The Microservice service I’m going to build could be enhanced to allow for updates, deletes, etc. by using a back end like SimpleDB (or other options) but to keep this article rather short and easy I won’t add that functionality. With some playing around I think you would find this to be very easy given the documentation AWS offers.

To start with you will need an AWS account. If you sign up now you actually get a lot of things to try for free for a year. Log into AWS API Gateway and create a new API called MyMicroservice as seen in the image below:

AWS API Gateway Create New

Go ahead and create that new API. In the screen that follows you will now have the opportunity to create a method, resource, or delete the API. Click the Create Resource button and on the screen add the following:

Creating an API resource

Click on the Create Resource button. Create another resource under the api resource like so:

Adding the v1 resource

Click on the Create Resource button.

Since we are building a simple Microservice we will have this do one thing: Return the kinds of MOBs in the game Minecraft. I did something similar a while back with Python 3 and Flask. Our API for this microservice will look like this: /api/v1/mobs/{type}

We need to create another resource for the mobs:

Adding the MOBs resource to the API

With the current result looking like this:

API listing

The final resource we need is a special one that will take a custom parameter. For this we use curly brackets as instructed by the AWS help text on the create resource screen.

Adding the custom parameter

So the final API layout will be:

Final API layout

Now we can add our one and only method: GET. Click on the /{type} and then press the Create Method button. Set it the same as the screenshot:

Adding the GET method to the type resource

You might get a warning like: “You do not have any Lambda Functions in us-east-1. Create a Lambda Function” — this is okay. Go ahead and click the Create a Lambda Function link.

Create a new Lambda function

In the screen that comes next you have the option to Select blueprint. In the search box type hello and you should see an option for hello-world-python which you can click on. The next screen is the Configure function screen.

Modify the existing code from:

from __future__ import print_function

import json

print('Loading function')

def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))
    print("value1 = " + event['key1'])
    print("value2 = " + event['key2'])
    print("value3 = " + event['key3'])
    return event['key1']  # Echo back the first key value
    #raise Exception('Something went wrong')

To this:

def lambda_handler(event, context):
    mobs = {
        "passive": ["Chicken", "Cow", "Horse", "Ocelot", "Pig", "Sheep",
                    "Bat", "Mushroom", "Squid", "Villager"],
        "neutral": ["Cave Spider", "Enderman", "Spider", "Wolf",
                    "Zombie Pigman"],
        "hostile": ["Blaze", "Creep", "Endermite", "Ghast", "Magma Cube",
                    "Silverfish", "Skeleton", "Slime", "Spider Jockey",
                    "Witch", "Whither Skeleton", "Zombie",
                    "Zombie Villager", "Chicken Jockey", "Killer Bunny",
                    "Guardian", "Elder Guardian"],
        "utility": ["Snow Golem", "Iron Golem"],
        "boss": ["Whither", "Ender Dragon"]
    return {"mob_type": mobs[event['mob_type']]}

Set the rest of the values as seen in the screenshot below:

Setting up the Lambda function

For the Role dropdown select the value: Basic execution role

Choosing the basic execution role value

In the pop-up window take the defaults and press Allow.

Back in the Configure function press Next.

Create the function:

Create the Lambda function

The completed Lambda function

Go back to the Gateway API page and add the new Lambda function.

Add the new Lambda function to the Gateway API

Once you save that you are put into a test screen but first you need to do something else before you can test this out. Click on the Integration Request link:

Test Screen

Click on the Mapping Templates and add application/json to the Content-Type (even though it looks like it defaults to this do it anyway). Click the little checkbox icon and Input Passthrough will show up. Click on the edit icon for that (the little pencil). Select Mapping Template from the dropdown and add the following to the large textbox:

    "mob_type": "$input.params('type')"

Saving the mapping template

Click the little checkbox icon to save the settings. Click on the Method Execution link at the top and then click on Test.


Try it with some other type options like neutral:

Now go back to the AWS Gateway API control panel and click on the Deploy API button:

Deploying the API

Fill out the winodw that pops up as follows:

Deploy API settings

Once you save that you should be presented with the URL you can use to test it in your browser:

The full URL to test with

Note: Make sure to click on the left hand side of the API tree to the GET

Open the link in a browser making sure to set the type value. Keep in mind I didn’t add any validation so invalid values will cause problems.

Results in a web browser

That’s it! Once you’ve worked through this a bit and play around its actually very easy to work with. Keep in mind you can also set security on these endpoints if needed – I left mine publicly open for this tutorial. Also, you can easily hook up other AWS services easily like S3 or perhaps have a custom domain address for your new API with Route 53. That’s just the tip of the iceberg. Explore around and you will see logging options, metrics, etc. Good luck!

Post to Twitter

This entry was posted in Amazon Web Services, Python. Bookmark the permalink.

5 Responses to Build a Python Microservice with Amazon Web Services Lambda & API Gateway

  1. Rajnish says:

    Really good tutorial to get started on AWS API Gateway. Loved it.

  2. David says:

    I love your tutorial, really good stuff! I went through the steps but all I get is

    message: “Missing Authentication Token”

    I’m not sure how to troubleshoot. Any ideas?

  3. David says:

    Maybe I missed a step, but I think you may have missed the step to change the Integration Response to say:


    For me at least the response contains the full header, request, lots of response headers, etc. I had to set it to the above value to get it to work. Also NVM about my last question, the problem was the API hadn’t gone visible yet (going live delay).

  4. John Sobanski says:

    Great article. Thank you for writing this.

  5. Larry Grant says:

    David, I suspect the error was because you only tested

    https://{your unique id}

    instead you need to add the full request to the end of /prod


Comments are closed.