AWS Big Data Blog

Powering Gaming Applications with Amazon DynamoDB

Nate Wiger is Principal Gaming Solutions Architect for AWS.

Dave Lang, Senior Product Manager for Amazon DynamoDB, also contributed to this article.

Amazon DynamoDB is rapidly becoming the go-to database for many of the fastest-growing games in the world. Games like Fruit Ninja (from Halfbrick Studios) and Battle Camp (from PennyPop) have leveraged Amazon DynamoDB’s push-button scalability to seamlessly grow their games to millions of players. Amazon DynamoDB has also been adopted by developers like Supervillain Studios, maker of games like Tower Wars and Tron Evolution.

In this post, you’ll learn how Amazon DynamoDB can help you quickly build a reliable and scalable database tier for a mobile game. We’ll walk through a design example and show how to power a sizable game for less than the cost of a daily cup of coffee. We’ll also profile a fast-growing customer who has scaled to millions of players while saving time and money with Amazon DynamoDB.

Importance of the database tier

When architecting an application for scale, one of the key factors is the database tier. This is especially true for games, which are extremely write-heavy. Game data is continuously updated as the player collects items, defeats enemies, receives gold, unlocks levels, and completes achievements. Each event must be written to your database layer so it isn’t lost. Players get very grumpy when you lose their progress.

Developers of games and web apps often use an open-source relational database such as MySQL for their database layer because it is familiar. Unfortunately, relational technologies such as MySQL were developed in an era of read-heavy workloads, which doesn’t apply to games, social media apps, and photo sharing sites. This has spawned NoSQL solutions that trade relational query flexibility for high write throughput and horizontal scaling.

Three reasons why Amazon DynamoDB is a great option for game developers

  • Amazon operates it for you

    You’re busy making a game, right?  Amazon DynamoDB is a managed service that includes full operational support and multi-data center high availability. You don’t have to worry about installing software, dealing with hardware failures, or tuning for performance.

  • You can grow or shrink Amazon DynamoDB with a single API call

    Each Amazon DynamoDB database table is associated with a throughput capacity. You can specify 1,000 writes per second and Amazon DynamoDB scales the database behind the scenes. As your needs change, you update the capacity and Amazon DynamoDB re-allocates resources as needed. This elasticity is a huge help to game developers: if your game takes off, you might suddenly scale from a few thousand players to millions. Just as important, you can quickly scale back down—very challenging with sharded MySQL databases.

  • Performance is consistent as your game grows

    Amazon DynamoDB maintains predictable, low-latency performance at any scale, which is crucial if your game grows to millions of latency-sensitive customers. You won’t spend any time tuning the performance of Amazon DynamoDB.

Saving Game Data in Amazon DynamoDB

Let’s imagine you’re creating a role-playing game. Your game design features common mechanics: fighting monsters, collecting loot, and leveling up. You need to save a user’s progress, so you create a profile for each player with key-value pairs for things like items, level, and amount of earned gold. Your data structure might look something like this:

{
    player_id: 3612458,
    name: “Gunndor”,
    class: “thief”,
    gold: 47950,
    level: 24,
    hp_max: 320,
    hp_current: 292,
    mp_max: 180,
    mp_current: 180,
    xp: 582180,
    num_plays: 538,
    last_play_date: "2014-06-30T16:27:39.921Z"
}

In this example, player_id is a unique value. Mapping this to a relational database like MySQL is straightforward: create a column for each key. This works, but it’s a lot of database overhead for parsing and indexing every column of a structure that is almost always fetched based on the primary key (player_id). It’s unlikely you’ll query for a player record based on hit points or experience.

So let’s see how this maps to Amazon DynamoDB. With Amazon DynamoDB, we define only the columns we want to index. In this case, we’ll create a single hash key as the primary key, using the player_id since it is unique. We’ll define a table called “player_profiles” and set the hash key to “player_id.”  Here’s an example in Python:

    player_profiles = Table.create(‘player_profiles', schema=[
        HashKey('player_id', data_type=STRING)
    ], throughput={
        'read': 5,
        'write': 5,
    },

We’ve created a table with 5 read capacity units and 5 write capacity units, which falls within the AWS Free Usage Tier. You can also use the AWS Management Console to create the table. It’s easy to learn how.

Once this table is created, we put and get profiles:

    player_profiles.put_item(data={
        'player_id': '3612458',
        'name': 'Gunndor',
        'class': 'thief’,
        ...
    })

    profile = player_profiles.get_item(player_id='3612458')

These examples are in Python, but you can use any AWS SDK to put/get keys in Amazon DynamoDB.

Primary Key Value

Relational databases use auto-incrementing integers, which are typically used as the primary key. At scale, auto-incrementing primary keys become a bottleneck, so NoSQL stores like Amazon DynamoDB don’t include them. So how do we generate unique player_id values?  We use a UUID, which different clients can generate independently because UUIDs are unique. A UUID gives us a long string such as a8098c1a-f86e-11da-bd1a-00112444be1e.  A UUID is a great fit for Amazon DynamoDB because it helps ensure primary keys are randomly distributed and accessed, which in turn ensures the best performance from Amazon DynamoDB.

Generating UUID’s is simple:

    player_id = uuid.uuid1()
    player_profiles.put_item(data={
        'player_id': player_id,
        'name': 'Gunndor',
        'class': 'thief',
        ...
      })

Atomic Increment

In addition to put and get, Amazon DynamoDB supports atomic increment. This is useful for updating values as they change because multiple requests from your application won’t collide— a common source of bugs and lost progress in online games. If a player picks up 100 gold, you can just tell Amazon DynamoDB to automatically increment the gold by 100 as opposed to having to get the record, increment the gold, and put it back into Amazon DynamoDB.

Choosing the right capacity level

Amazon DynamoDB lets you specify how much throughput capacity you need. But what if you don’t know? When you start to develop your game, create your first table in the free tier (such as 5 write capacity units and 10 read capacity units). As traffic increases, use CloudWatch graphs in the Amazon DynamoDB Console to monitor usage and make changes.

Another useful tool is Dynamic DynamoDB, an open source library that helps you auto-scale your table’s capacity. One of our customers, tadaa, used Dynamic DynamoDB to react to a drop in traffic levels and therefore reduce costs.

Can I really support thousands of players for the price of a daily cup of coffee?

Yes! Let’s use the game-save use case to estimate costs. Suppose your game averages 100,000 active players per month. Most players aren’t active at once, so let’s estimate 1/10 playing at any moment. Let’s also assume these 10,000 concurrent players save their game state once a minute and the record size for each player’s data is less than 1 KB. Let’s also assume that each player needs to read their game state out of the database once per minute. Since there are 60 seconds in a minute, your Amazon DynamoDB table must support about 167 writes and reads per second (10,000 / 60). Most companies give themselves buffer capacity, so let’s round up to 200 writes and reads per second and throw in 50 GB of storage.

Based on current pricing in the US-EAST-1 region, this would cost about $4.16 per day!  You could support 100,000 players per day for the cost of a cup of coffee (one of the fancy espresso drinks, anyway). And you can get started with Amazon DynamoDB for free using the AWS Free Usage Tier.

Customer Example: Battle Camp 

Battle Camp, a popular mobile game published by PennyPop, uses Amazon DynamoDB as its primary data store. Battle Camp has been downloaded more than 10 million times and is consistently on the list of the top 100 highest-grossing apps in over 40 countries. After looking at several other NoSQL options, they chose Amazon DynamoDB because they wanted to focus on application programming, not server maintenance and scaling.

Developers at Battle Camp started by dowloading fake_dynamo, an open source client, to do local development. (Amazon also released and supports a local Dynamo client.) They built their own ORM to use with Ruby on Rails. The ORM simplifies a lot of DynamoDB’s features such that they only use key-value retrieval in the application layer. The ORM stores the value of the body as a JSON object, which is GZIPed to base64 string. This allowed them to compress a raw JSON object down to 10% of its original size. They migrated from MySQL into DynamoDB. Most web application database queries can be reduced to simple fetch and saves, and migration was done in a few weeks–including building their custom ORM.

The figure below illustrates how Battle Camp has integrated Amazon DynamoDB into their architecture.

The results? Huge savings in time and cost. As Charles Ju, co-founder of PennyPop, explains:

“Amazon DynamoDB’s cost savings aren’t just through efficiencies and ease of use, but through lowering the cost of maintenance. Building, maintaining, and sharding large live data-centric real-time projects is incredibly hard and requires many people to create and maintain these projects. We still only have two server engineers running a MMORPG where millions of players come to enjoy the game. We are leaner than any other MMORPG at our size that I know of.”

At larger scale, they also found that DynamoDB also works well with MapReduce analytics protocols because of the scaling flexibility. They build their MapReduce protocol in house to parallelize their data analytics.

One last word: Analytics

In addition to real-time game services, Amazon DynamoDB integrates with other AWS services like Amazon Elastic MapReduce (EMR) and Amazon Redshift. Both Amazon EMR and Amazon Redshift support loading analytics data directly from Amazon DynamoDB, making it easy to build an analytics workflow. If you’re interested in learning more about analytics for gaming on AWS, comment on this post and we’ll dedicate a future post to that topic.

If you have questions or suggestions, please leave a comment below.

———————————————

Related posts:

Analyze Your Data on Amazon DynamoDB with Apache Spark