Case study: How Butterscotch Shenanigans keep a Levelhead with AWS
The games industry is a crowded and competitive place. A studio could spend over a year developing a game, to launch it alongside thousands of other new titles.
In this hypercompetitive world of video games, it can be difficult for any game to succeed. And if you’re an independent developer, how can you cut through the noise without an unlimited budget and workforce?
Adam Coster, indie game studio CTO, says it all comes down to good tech.
Butterscotch Shenanigans make games with an increasingly social design. Crashlands went on to be named in TIME Magazine’s top games of 2016, and more recently, the team have gone on to launch their latest title Levelhead.
As an independent studio of 5, the team faced a tough challenge to balance building infrastructure with what matters most to a game developer, creating features for players to enjoy. “I had to make sure that I personally knew how to manage every aspect of creating, deploying, scaling, and managing our web infrastructure. The time spent managing that resulted in fewer features for our players. It also meant I was spending less time developing the skills needed to innovate and experiment with new features,” said Adam.
After realizing this cost, Adam decided to search for a solution that would allow Butterscotch to exclusively focus on the biggest value-add for their players. “In that ideal world, all we would do is design and code, and the rest would just take care of itself. We decided to use AWS as it was constantly releasing new services and showed no evidence of slowing down.”
Adam went on to say, “AWS continues to add more and more support for containerization, better build tooling, and many high-level services that abstract away more and more deployment details. I’ve taken advantage of these as they’ve appeared, and I am now quite happy to say that I really do get to spend my days designing and coding up new business logic. I spend almost no time at all managing builds, deployments, or infrastructure.”
Butterscotch Shenanigans has been continuously centralizing its web tech to be integrated with their core website at bscotch.net; below Adam shares a short summary of the site’s development and deployment ecosystem:
Our local development environment uses docker-compose to mimic (as closely as possible) the remote architecture. Fortunately, the use of containers makes this pretty straight forward.
When I’m ready to deploy a feature, I simply git-push my “master” branch. A few minutes later the dev deployment of the site now has that feature. When I’m ready for that feature to go live, I click a button on the dev site to promote it to a beta deployment. Finally, when I’m confident that the feature is ready for prime time, one more click promotes the build to production.
How does this work?
- CodeBuild, connected to BitBucket, triggers builds whenever something is pushed to the project’s master branch. CodeBuild creates the docker image for the site, and dumps the build artefact, a “Dockerrun.aws.json” config file, into Amazon S3.
- An AWS Lambda function is triggered by the appearance of that file, and tells AWS Elastic Beanstalk to use that config file to redeploy to the dev environment.
- When I click an admin-only “Promote” button on the website, the backend sends an API request to another Lambda function that tells the appropriate Elastic Beanstalk environment to deploy the new build.
- On boot, the deployed backend uses its AWS credentials (automatically provided to it by Elastic Beanstalk/Amazon EC2) to request encrypted key-value pairs from the Parameter Store, which it uses as environment variables for connecting to production databases and 3rd party services. This makes it extremely easy to securely manage environment variables between deployment environments.
Games have both predictable daily usage patterns and unpredictable usage bursts due to external events (a big YouTuber can cause a game to go from obscurity to wild success overnight). The site auto scales its resources based on usage, so we get to keep costs low while concurrent usage is low, and not worry about what will happen if player numbers suddenly soar.
How does this work?
- Trivially! Elastic Beanstalk provides a breadth of configuration options to allow for it.
On the site, images are resized on-the-fly and cached so that users with different screen resolutions get appropriately-sized images without wasting their (or our) bandwidth.
How does this work?
- We originally set this up long ago, making our own variation on what others have done. AWS now has an official deployment guide for this very use case.
Our newest game, Levelhead, automatically provides daily challenges to our players based on both user-generated and official content. This needs to happen super reliably, on a schedule.
How does this work?
- Our website’s API provides search functionality to get the data needed to create these challenges.
- Lambda functions use our API to fetch the data and compile it into new assets, then send those assets back to our API.
- An Amazon CloudWatch Event Rule uses a cron expression to trigger the Lambda functions every day.
Most of the functionality we’re adding goes right into our API, but here and there it makes sense to spin up some other AWS service for another feature. Lambda serves as a great starting point for experimenting with features I may want to add later, and for managing cron jobs. And while we use other 3rd party services for some central features (e.g. database hosting), those services in turn are built on AWS. So, even in cases where AWS doesn’t yet have the tooling we need, I still get to take advantage of low latency from having the entire stack live in AWS.
Learn more about Amazon Game Tech solutions by visiting the website.