I can serverless, and you can too!

James Beswick
ITNEXT
Published in
11 min readMar 19, 2019

--

Learn how to use a serverless approach to build a complex mobile app for a zoo.

One of the biggest barriers to going serverless is getting through the mental hurdles of using other people’s services to create your architecture. It’s not always natural if you come from traditional software development and can take some practice. But don’t worry — if I can serverless, you can too — and I’m going to show you how.

AWS has services for almost everything so let’s see how we can put these to good use in building a complicated mobile app. There’s no code ahead — this is purely an architectural exercise for anyone nervous about designing for serverless!

And don’t worry — there are endless ways to build this same app, so if you have other ideas, let me know in the comments.

Welcome to the zoo

Our client has a zoo. It has 25,000 visitors a day, with up to 50,000 during special events and holidays. The zoo features 100 separate exhibits.

They need to create a mobile app for visitors to drive engagement and repeat visits. They expect around 50% of visitors will use the app because they will promote discounted tickets for app users.

I met with the zoo owners and this is what they told me:

  • It should be downloadable from the standard app stores.
  • Offer both anonymous and logged in modes, supporting common social logins and maybe custom email/password authentication.
  • Visitors can use their location at enclosures to learn about the animals, and scan barcodes hidden around to learn about any one of the zoo’s non-human guests.
  • All users can watch videos relating to the exhibits, but logged in users get exclusive content.
  • Visitors can upload photos but we have to ensure the content is appropriate — remember, there are kids around.
  • Visitors will receive alerts when they are in the zoo, pushed by zookeepers for feeding time and ‘Meet the Animal’ lectures.
  • They would like disabled visitors to have access to text-to-speech for any placards located around the facility.
  • Translation for overseas visitors would be great (covering as many languages as possible since everyone in the world comes here).
  • Visitors can “like” an exhibit and receive alerts when significant events happen.
  • This need to be thoroughly tested and “just work” because they have limited IT support available and cannot manage app problems from 25,000 guests a day. And of course they expect 100% up-time.

It looks like we have our work cut out, so let’s brainstorm on how serverless can get this done. I put all the major items on Post-Its so we can keep track:

Why not just use the ‘old way’ to make the app?

If we didn’t have serverless, this would be very complicated. This client doesn’t have much IT help so it will be a difficult project with ongoing maintenance. We will need to work out how many servers are needed to support potentially 25–50k users on a daily basis. We will need iPhone and Android development teams with a testing strategy for handling all the most popular devices.

We also require OAuth setups with the main social providers and a user database somewhere, along with all the password management and reset processes. Then there’s video hosting, but we can’t use YouTube because some of the content is gated. To build all this out, we will have to consider how many developers are needed and the sort of maintenance overhead for this kind of infrastructure.

The goal of the serverless approach is to really minimize most of what’s in the last two paragraphs. From a practical standpoint, a large amount of your development budget and personnel can disappear in racking-and-stacking hardware, and managing authorization, databases and mobile deployments.

Part of the “serverless mindset”, as Ben Kehoe calls it, is redeploying all those resources into building valuable functionality that your customers can see, touch and care about. This is all about customers — our zoo visitors care less about our infrastructure and more about when the giraffes will be fed.

Shorty The Giraffe is counting on you! Credit: https://www.freepik.com/free-vector/giraffe-portrait-cartoon-style_1195871.htm

The broad requirements

There are few requirements that aren’t specifically serverless but in the spirit of using managed services and being frugal with our resources, we should address these up front:

We could build this as a web application using a single-page application framework like React or Vue. But the zoo owners really want an app, and it sounds like they will send push notifications for special offers at some point in the future (sounds like an extra requirement?).

The front-end work is out of scope for this exercise but we should look at cross-platform mobile development to avoid building the same app twice for iOS and Android. React Native could be good option, and so could Flutter. Either way, we want the front-end to be a manageable and easy to build.

Testing mobile apps is tricky and, due to the proliferation of Android versions and devices out there, can be cumbersome. The owners didn’t really say much about this but with minimal IT help, automating this process is clearly going to be helpful. AWS Device Farm provides an automated solution to this problem using a massive fleet of actual devices.

This is also a good time to find services or requirements that might not fit the budget of the client. For example, the 100% up-time requirement will be expensive to architect but if the zoo is prepared to accept 99.99% up-time (unavailable for less than 1 hour a year), this significantly changes what we need to build and makes a huge difference to cost. The trade-offs are really important to consider before we start building.

What services do we need?

The very first step in figuring this out is looking at services you might need, and you can deduce some of these from the requirements. I scribbled my immediate thoughts down (red for data-related items and blue for everything else):

For data-related items:

  • Video hosting requires only S3 for storage and we can deliver the content through CloudFront. In this case, CloudFront can also help us restrict some content for logged-in users using signed URLs or cookies.
  • The photo uploads can also be stored in S3. Some image recognition will go a long way to helping us detect appropriate images — maybe Rekognition?
  • There’s going to be a list of daily events and alerts from zookeepers — I think we can manage the schedule in DynamoDB. The alerts I’ll cover a little later.
  • The authentication described is fairly ordinary and can be handled by Cognito. This also supports tracking of anonymous users so we can remember settings and preferences if the user later converts to a logged-in user.

For everything else:

  • For text-to-speech, we’ll use Amazon Polly to create the audio, which we then store in S3 for playback.
  • Language translation can be achieved with Amazon Translate, which currently supports 21 languages from English.
  • For exhibits alerts we could use SNS to allow visitors to subscribe to exhibits.

This phase is a broad sketch but it gives us an idea of which services we will wire up. Each one of these tools is a fully managed service so we just need to know how they work and how to connect them.

Handling the text, images and videos

For binary data like images and videos, S3 is always the obvious choice. In fact, by integrating some Lambda functions that run when new objects arrive, we can make S3 the workhorse behind much of this functionality.

The zoo app could have an S3 bucket with folders for each exhibit, structured like this:

Each sub-folder represents types of content in the system:

  • When exhibit descriptions are saved by a zoo administrator, this fires a Lambda function which calls AWS Translate to convert the text into other languages, and stores the results in language-specific folders (‘es’, ‘de’, ‘it’, etc.). This solves the translation problem because it only needs to happen once each time the content is updated (and not when end-users switch languages).
  • Description changes can also trigger a Lambda that sends the file to Polly — we can save the resulting speech in the audio folder and playback whenever a user requests. This can be done for multiple languages.
  • When videos are saved, this event triggers a Lambda which uses Elastic Transcoder or the Elemental MediaConvert service to reprocess video for different sizes and prepare for viewing on demand. This will help with performance and bandwidth costs. It only needs to happen once per uploaded video.

Finally, for user-generated photos, we will use a separate bucket that triggers a Lambda to analyze the photo in Rekognition. We can use the moderation labels in this service to find unsafe content, and we can detect if the photo is an animal. We can examine the response from Rekognition and decide what to do next — if it’s borderline or suspect, we will flag the image for a moderator before adding to the primary bucket’s images folder:

The zoo schedule

For upcoming events throughout the day, let’s use a DynamoDB table to store information about feedings, lectures and other zoo events. Visitors only care about the events for the current day while they are in the zoo:

The front-end app will query this table using a time range for all the events during the day. Zookeepers will use a separate administration tool to set up events. The front-end will alert users when an event is about to happen, maybe filtering for exhibits the user has liked (using the exhibitID attribute).

DynamoDB is an extremely fast and scalable storage option for this kind of data. The schedule could equally have been stored as a flat file in S3 — you could experiment to find the pros and cons of each approach.

Notifications

There are a number of sources for notifications in this app — upcoming events, special alerts and things happening at ‘liked’ exhibits — all stored within a single DynamoDB table. While the app retrieves the initial state when it starts, it then must listen for changes in the data (in case events are canceled or the schedule changes).

There is a simple way to handle the notification requirements. We can set up an SNS topic for each exhibit throughout the zoo. If a visitor ‘likes’ an exhibit, effectively subscribing to events happening there, we only need to subscribe the user to that SNS topic.

Potentially this subscription is only for day of the visit so it can be reset after the zoo closes. SNS can handle up to 10 million subscriptions per topic so we are well within the limits. This approach avoids managing a massive table of liked exhibits (between 25,000 daily users and 100 exhibits).

How can we make this realtime? DynamoDB can publish changes to a stream, which can fire a Lambda and publish to an SNS topic. This can then publish to AWS IoT to push the alerts to the front-end. Alternatively, if we are using AppSync or Amplify, we can explore push notifications with those services. Text messaging is also possible, though much more expensive ( $0.00645 per message), or we could use email via SES.

Bringing it all together

Connecting the front-end and the back-end happens via API Gateway, one of the most important services in the entire serverless ecosystem. We can develop an API that allows the front-end to get lists of exhibits and events, and make subscriptions to exhibits:

Cognito will be handling authorization and be responsible for issuing tokens and managing identities, while the gateway will be deciding whether anonymous or logged-in users can access certain routes.

When you piece together all the various services and our Lambda functions, we have developed a back-end architecture that looks like this:

Throughout this exercise we haven’t mentioned scaling, load balancers or provisioning — instead, we have chosen to use massively scalable services that handle all this for us. This design can easily accommodate the traffic levels the zoo expects, and we will eventually write maybe only 1000 lines of code on the back-end to support the entire application.

One of the most exciting parts of serverless architecture is the enormous flexibility. In reality, features change constantly in applications, often in ways that can break traditional architecture. By contrast, this design is very resilient, and could easily accommodate many future changes.

Additionally, we have focused on building a distributed system instead of a monolith. Many of the individual parts like the language translation or image detection don’t know about the rest of the system and can act independently. This is one of the hallmarks of serverless architecture and one the reasons it scales so effectively.

We Built a Zoo (app)

We have developed a sketch of an architecture that will support the initial requirements. But imagine how the app changes if:

  • The zoo expands or starts a chain — how do we support multiple parks?
  • The owners want to add ‘missing child’ alerts.
  • Members can sponsor an animal and pay through the app.
  • We enable a feature that allows people in the park to find each other.
  • Visitors can buy lunch through the app and pick up at the food court.

Hopefully this exercise also shows how a serverless approach helps keep you focused on the client problem rather than the technical solution. If you can understand the requirements and then decide which services to use, this will help minimize the amount of custom code you are writing and, consequently, how much you will need to support and maintain.

--

--

Aspiring fiction writer by night. Opinions here are my own. See my tech posts at http://bit.ly/jbeswick.