Stack overviewWe separated the technology stack into three main tiers, each consisting of several sub tiers and I'll discuss each one of them in more detail.
- The mobile app
- The back-end API
- The cloud hosting stack
1) The mobile appWhen we decided to start Rumar Gaming there was no doubt that we would be using Xamarin for our mobile development. Our games need to support both iOS and Android, so using a cross-platform development environment can cut our development times significantly. In my opinion, Xamarin is by far the most mature option for cross-platform mobile development. Add the fact that I'm an expert at C# and already have experience developing games in Xamarin and it was a done deal. The mobile app itself consists of three tiers (from the bottom up): Rumar Framework This is our custom framework which contains the interfaces and logic that are shared by all the games. Aside from holding some utility classes, its main responsibility is communication with the API to handle - among other things - device registration, session management, score registration, in-app purchases and advertisements. The framework is mainly cross-platform, but has some platform-specific functionality on top of it as well. For example, in-app purchases need to be handled differently in iOS and Android. Game-specific logic This tier contains cross platform, game-specific logic. We try to put as much of the game logic in here as possible so we only have to develop and manage it once for both platforms. iOS- & Android-specific logic You will always need to have separate projects for each of the supported platforms because of platform-specific logic that is required.
2) The back-end APIThe games need a back-end that handles things like registration of devices, session management, push notifications, authentication and score tracking. Again, the goal here is to share as much logic as possible through one framework API, but some game-specific functions will get their own API. We've decided to use the .NET Web API framework for this, mainly because of our long history with .NET. The main alternative for us was node.js, which would be somewhat easier to scale, but because of a limited development timeframe we decided not to take the risk of choosing a technology we are not yet comfortable with. By hosting the API on Windows Server Core instances, we are still able to cut down on hosting costs. More on this will follow in the next section.
3) The cloud hosting stackNo one can predict if (one of) our games will become a hit, although we are certainly doing our best covering all grounds to increase our chances. If a game does become successful, the back-end must be highly scalable. It should not matter whether we have 10 users or 1 million users, the back-end should perform in the same way and it should not require a lot of effort (ideally, not any effort) to scale it up. So we are hosting the back-end in "the cloud" and we have chosen Amazon Web Services (AWS) for this because we have been really satisfied using it in the past. I'm definitely not suggesting you should not look into other services like Microsoft Azure or Google Cloud Services! AWS was the best fit for us, but it may be different in your situation, so I encourage you to do a comparison yourself first. Let's take a look at the moving parts of our cloud hosting stack. EC2 The API will be hosted on EC2 instances. EC2 stands for Elastic Computing Cloud and offers you virtual machines to host your application. They can be automatically scaled up and down depending on traffic and performance requirements, meaning that - during upscaling - new instances are automatically deployed and added to the load balancer. By hosting our API on Windows Server Core instances we save money on both licensing and computing. Core instances require less system resources, are deployed faster and because you don't get a full Windows interface you pay less money for their license (which is integrated in the costs per hour). Cognito Cognito is used for authentication and user management. It offers several authentication providers and out of the box functionality for user data synchronization. When a player starts a game session, we can start storing user data (such as game preferences) on the device. If the player gets authenticated at some point - by creating an account or using a social login provider - the offline user data will be synchronized to the cloud. S3 Amazon's Simple Storage Service (S3) is used when an app requires to store blob data such as images or videos. The keyword here, again, is scalability; we don't need to worry if we store 1 asset or 1 billion assets, it will just work and we only get billed for what we use. SNS SNS stands for Simple Notification Service and it's used to register devices for push notifications and to send the notifications. It supports both iOS and Android so that's perfect. You only pay when you are sending out notifications and even then it's free for the first million notifications. DynamoDB DynamoDB is AWS's answer to No-SQL databases. It will be used to keep track of game sessions, progress and high scores. No-SQL doesn't necessarily have to be the best choice when developing a mobile API, but it is certainly the easiest to scale and very cheap in use. So taking that into account - scalability and cost - DynamoDB seems to be the best choice for us.
Bottom up approachWhen talking about developing games, most people expect you to start with a game idea and design the rest around that. The question I get the most from my acquaintances is "do you guys have any cool game ideas yet?" Well yes, we do have some rough ideas, but that's not what we are focusing on in the beginning. We are taking a bottom up approach, meaning that we start with setting up the cloud hosting stack, then we develop the framework API and we slowly work our way up to the game logic. Even though we are really excited to start working on the actual games - which is definitely the most fun thing to work on - in order to create something that will scale and is future proof, we must start at the bottom.
Cost estimationThe monthly cost of this stack depends heavily on the size of your userbase and the requirements of your API, but I have worked out an estimation based on some assumptions. Development During development you're good to go with the Free Tier; the free tier is available for the first 12 months. The numbers below are based on monthly use. EC2
- 750 hours per month of EC2 time (so that's one instance for a full month)
- t2.micro instance: 1 vCPU with 1 GB RAM (you can run Windows Core on this)
- 5 GB storage
- 15 GB data traffic
- 20.000 Get requests
- 2.000 Put requests
- Up to 1 million push notifications sent.
- 1 million sync requests per month
- 10 GB sync storage
- You have 1.000 daily users.
- Users generate 10.000 sessions daily.
- Users generate 500.000 API requests daily.
- Each daily user is unique (for sake of Cognito calculation)
- A user profile contains 100kb of data.
- Each user received 10 push notifications daily.
- Each API request triggers 5 database requests.
- 500.000 API requests daily will average to around 6 requests per second.
- Your API can run fine on a 1 vCPU / 4GB RAM system.
- In that case a t2.medium instance will suffice, total costs: $56
- Scaling works by adding more machines, thus multiplying these costs.
- Monthly sync operations: 10.000 sessions * 31 days * 2 syncs per session = 620.000
- Monthly charged: (620.000 / 10.000) * $0.15 = $9.30
- Profile storage: 31.000 users * 100kb = 3.1 GB * $0.15 = $0.47
- Free tier for the first 12 months!
- After that: $9.80
- Monthly notifications: 31.000 users * 31 days * 10 notifications = 9.61 million
- Monthly charge = 9.61 * $0.50 = $4.80
- Total requests: 500.000 API requests * 5 databases requests * 31 days = 77.5 million
- Total storage: 10 GB
- Free tier for the first 12 months!
- After that: $10 (very hard to estimate, but it's on the high end)
- You need 1 TB of blob storage, each user does 100 put+get requests daily.
- You want full backup of blob storage (highest price).
- Storage: 1 TB = $30
- Requests (100 GET + 100 PUT per user daily): 3.1 million GET + 3.1 million PUT = $31
- Total: $61