
This tutorial is part of the Quick & Dirty series for developing a custom Alexa skill called My Zoo.
Estimated time: 10 – 15 minutes
No programming experience necessary
Overview
With this tutorial, you’ll learn to use AWS DynamoDB storage (for free*) to store and retrieve data.
In a previous post (Add Persistent Data on Amazon S3 to a Custom Alexa Skill) we updated My Zoo to remind a returning user what animal they heard last time they visited the zoo. S3 is great, and several of Amazon’s official Alexa developer tutorials use it to store persistent data. However … Amazon has declared that using DynamoDB is a better option. So, let’s learn to use it!
* Alexa Development Console (ADC)-hosted skills, like My Zoo, along with its DynamoDB data storage, is limited in its free-ness. If you publish a skill and it becomes popular, you may need to move the skill to your own AWS account. But we’re just learning here, so don’t worry about that right now!
Prerequisites
- an Amazon Developer account, click here to create one (it’s free)
The instructions in this post are applicable to any custom Alexa skill coded with Python. If you wish to join-in on the My Zoo fun, complete these 3 mini-tutorials first (total estimated time: 25 – 40 minutes):
Ready? Let’s do it!
Use Persistent Data with DynamoDB
Note: if you previously used S3 to store persistent data, that’s ok. You can leave most of the S3 code in place, or delete it first.
Step 1: Add Code Requirements
First, we need to do programmer-techie stuff with code requirements. If you’re not a coder, no worries, just follow these steps:
- Log into the Alexa developer console and open My Zoo.
- Click Code on the top menu bar.
- Double-click the requirements.txt in the left column. The file will open in the editor window to the right.

- Add this line:
ask-sdk-dynamodb-persistence-adapter==1.15.0
The requirements.txt file should now look like this:

- Click Save.
Step 2: Apply Code Requirements
- Double-click the lambda_function.py in the left column. Or, if the file is already open, click the lambda_function.py tab above the editor window.
- Find this line in the editor window:
import ask_sdk_core.utils as ask_utils
- Create a new line below it, and add this code:
# import persistence adapter import os import boto3 from ask_sdk_core.skill_builder import CustomSkillBuilder from ask_sdk_dynamodb.adapter import DynamoDbAdapter # initialize persistence adapter ddb_region = os.environ.get('DYNAMODB_PERSISTENCE_REGION') ddb_table_name = os.environ.get('DYNAMODB_PERSISTENCE_TABLE_NAME') ddb_resource = boto3.resource('dynamodb', region_name=ddb_region) dynamodb_adapter = DynamoDbAdapter(table_name=ddb_table_name, create_table=False, dynamodb_resource=ddb_resource)
- If lines line of code exists, delete it (it was replaced with
CustomSkill Builder
above):from ask_sdk_core.skill_builder import SkillBuilder
The top section of code should now look like this:
# -*- coding: utf-8 -*-
#This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK for Python.
# Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
# session persistence, api calls, and more.
# This sample is built using the handler classes approach in skill builder.
import logging
import ask_sdk_core.utils as ask_utils
# import persistence adapter
import os
import boto3
from ask_sdk_core.skill_builder import CustomSkillBuilder
from ask_sdk_dynamodb.adapter import DynamoDbAdapter
# initialize persistence adapter
ddb_region = os.environ.get('DYNAMODB_PERSISTENCE_REGION')
ddb_table_name = os.environ.get('DYNAMODB_PERSISTENCE_TABLE_NAME')
ddb_resource = boto3.resource('dynamodb', region_name=ddb_region)
dynamodb_adapter = DynamoDbAdapter(table_name=ddb_table_name, create_table=False, dynamodb_resource=ddb_resource)
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.dispatch_components import AbstractExceptionHandler
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
logger = logging.getLogger(name)
logger.setLevel(logging.INFO)
- Scroll to the bottom of the file and find either this line:
sb = SkillBuilder()
or this line:sb = CustomSkillBuilder(persistence_adapter=s3_adapter)
- Replace it with this line of code:
sb = CustomSkillBuilder(persistence_adapter = dynamodb_adapter)
- Click Save.
Step 3: Save Data
Note: If you followed the tutorial Add Persistent Data to a Custom Alexa Skill using Amazon S3, you can skip Steps 3 and 4 because the coding to save and retrieve data is exactly the same, whether you do it with S3 or DynamoDB.
Next, update the CaptureAnimal intent logic created in Create a Custom Alexa Skill, Part 3 (Code an Intent) to store the most recent animal/sound pair retrieved.
A reminder about Python: formatting matters. Make sure lines are indented as shown.
- Find the CaptureAnimal intent code block by searching for this line:
class CaptureAnimalIntentHandler(AbstractRequestHandler):
- Scroll down the code block and create a new line after this one:
speak_output = animal + 's say ' + sound
Or, if you followed the instructions for saving persistent data to S3 in a previous tutorial post, find this line:attributes_manager = handler_input.attributes_manager
and replace it with the code below. - Copy/paste this code:
animal_attributes = { 'animal': animal, 'sound': sound } attributes_manager = handler_input.attributes_manager attributes_manager.persistent_attributes = animal_attributes attributes_manager.save_persistent_attributes()
Make sure attributes_manager ...
lines up with animal_attributes ...
.
The entire CaptureAnimalIntentHandler should now look like this:
class CaptureAnimalIntentHandler(AbstractRequestHandler):
"""Handler for CaptureAnimal Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_intent_name("CaptureAnimal")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
animal = handler_input.request_envelope.request.intent.slots["animal"].value
sounds = {
'bat': 'screech screech',
'bee': 'buzzzz buzzzz',
'cat': 'meow meow',
'chicken': 'cluck cluck',
'cow': 'mooooo',
'dog': 'bark bark',
'human': 'hello',
'lion': 'roar',
'monkey': 'chitter chatter',
'pig': 'oink oink',
'snake': 'hiss rattle hiss',
'zebra': 'whinny'
}
try:
sound = sounds[animal]
speak_output = animal + 's say ' + sound
animal_attributes = {
'animal': animal,
'sound': sound
}
attributes_manager = handler_input.attributes_manager
attributes_manager.persistent_attributes = animal_attributes
attributes_manager.save_persistent_attributes()
except:
speak_output = "I have not learned that animal's sound yet."
prompt = " Try another one!"
speak_output = speak_output + prompt
return (
handler_input.response_builder
.speak(speak_output)
.response
)
- Click Save.
Now, whenever a user asks for an animal and Alexa returns its sound, the last animal/sound pair will be saved to the S3 database.
Step 4: Retrieve Data
Note: If you followed the tutorial Add Persistent Data to a Custom Alexa Skill using Amazon S3, you can skip this Step because the coding to save and retrieve data is exactly the same, whether you do it with S3 or DynamoDB.
Add a returning user’s last animal/sound pair to their welcome message. If the user is new, stick with the standard “Welcome to My Zoo…” message.
- Find the LaunchRequest intent code by searching for this:
class LaunchRequestHandler(AbstractRequestHandler):
- Find this line:
speak_output = "Welcome to My Zoo, I make animal sounds! What animal do you want to hear?"
and replace it with this block of code:
# extract persistent attributes, if they exist attr = handler_input.attributes_manager.persistent_attributes attributes_exist = ('animal' in attr and 'sound' in attr) if attributes_exist: animal = attr['animal'] sound = attr['sound'] speak_output = "Welcome back to My Zoo! \ Last time you heard the {animal} {sound}. \ What animal do you want to hear now?" \ .format(animal=animal, sound=sound) else: speak_output = "Welcome to My Zoo, I make animal sounds! What animal do you want to hear?"
The entire LaunchRequestHandler should now look like this:
class LaunchRequestHandler(AbstractRequestHandler):
"""Handler for Skill Launch."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return ask_utils.is_request_type("LaunchRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
# extract persistent attributes, if they exist
attr = handler_input.attributes_manager.persistent_attributes
attributes_exist = ('animal' in attr and 'sound' in attr)
if attributes_exist:
animal = attr['animal']
sound = attr['sound']
speak_output = "Welcome back to My Zoo! \
Last time you heard the {animal} {sound}. \
What animal do you want to hear now?"\
.format(animal=animal, sound=sound)
else:
speak_output = "Welcome to My Zoo, I make animal sounds! What animal do you want to hear?"
reprompt = "I do not know that one. What other animal do you want to hear?"
return (
handler_input.response_builder
.speak(speak_output)
.ask(reprompt)
.response
)
- Click Save.
- Click Deploy, wait for it to finish.
Step 5: Test
The first time you test after adding persistent data, Alexa won’t have any data to pull from, so you’ll be welcomed as a new user instead of a returning user.
- Click Test.
- Enter
my zoo
. If you already have a separate browser open for testing, remember to refresh it first. You should see/hear the normal “Welcome to My Zoo, …” - Enter an animal that exists in our little database, for example
lion
. - Enter
bye
to close out the session. - Enter
my zoo
again. Verify you’re getting the returning-user welcome-back message “Welcome back to My Zoo! Last time you heard …”.

Pretty cool, huh?!
Step 6: (optional): Delete Persistent Data
In order to test the “welcome” message for new users, you’ll need to delete your persistent data (otherwise, you’ll always hear the “welcome back” message)
Delete persistent data directly from the AWS DynamoDB management screen (it’ll be easy, I promise!) Here goes:
- Click Code on the top menu bar.
- Between the top menu bar and the editor window, notice a line of icons.

- Find DynamoDB Database and click it.
- A new browser window will open to the Amazon Web Services (AWS) DynamoDB management console. This is where the persistent data is written to a database table. Persistent data tables are listed in the middle column, with a really long string for a name. If you have multiple skills using DynamoDB, there’ll be a different table for each.
Each user session will have its own row in the table, as seen in the right column.
There are two columns in the table: the id is there user_id, and attributes should look familiar!

- Click the box next to id for the row.
- Click Actions button.
- Click Delete to confirm.
- You can safely close the AWS DynamoDB browser window.
Now if you go back and test again, you should see the new user welcome.
Conclusion
Congratulations! You now know how to save and retrieve persistent data from an AWS DynamoDB database. Knowing how to do this will open many options for extending the features of your custom Alexa skills.
If you have corrections or suggestions for this tutorial series, please add a comment below.
Leave a Reply