This week, we’re going to hear from Marco and Spreaker about using API Gateway as a proxy around third-party services. Proxying other services helps you have a more stable API, and potentially switch out providers without needing to update your clients. Spreaker used API Gateway, Node.js, and Lambda to deliver audio ads to their Android app.
Tell me a little about Spreaker, what sort of challenges do you see hosting podcasts? Do you try to be a one-stop-shop for people that want to host podcasts or do you have a specific focus?
Spreaker is a podcasting platform allowing you to create, distribute, measure, and listen to audio shows either live or on-demand. We launched Spreaker back in the 2010 and it evolved a lot over time. Today Spreaker is a comprehensive solution to host and distribute podcasts and radio shows.
What part of Spreaker did you move to Lambda? Is it something you consider small, or is it a key part of your user experience?
Spreaker’s business model is based on premium subscriptions. A podcaster can host its own podcast on Spreaker for free, but if you want to get more features or more audio storage, you can pay (starting at few dollars per month) to upgrade to a PRO account.
We recently signed an agreement with Triton and we just started to deliver audio ads on our Android app. The Android app is the first place we experiment with new features before porting them to web and iOS.
The audio ad serving is managed by a set of AWS Lambda functions, accessible with an HTTPS interface provided by AWS API Gateway: it basically acts as an intelligent proxy over Triton and other ad agencies we’re in the process of adding.
There are a couple of good reasons to proxy all audio ad requests instead of directly calling the 3rd party advertiser server. Introducing a proxy you can write some logic on the server side, so you can make changes without touching your mobile apps, and you can send all traffic over HTTPS. Unfortunately, many ad servers out there still only support HTTP.
Other than Lambda, what other technologies did you use? This includes frontend, mobile, databases, whatever you can share.
We use a bunch of technologies. Spreaker has a pretty complex infrastructure and delivers tens millions of requests per day. To keep it simple, the web application (website and API) is backed by PHP, Node.js, PostgreSQL, Redis, RabbitMQ and Sphinx. We also run a multi-region live audio streaming application developed internally in Java on the great Netty framework. We have mobile applications for iOS and Android, both written in the respective native language, and we finally have a constellation of microservices to run asynchronous jobs.
Was this a rewrite of an existing product? If yes, why did the client want to replace the existing solution. If no, how was the decision to use Lambda made?
The ad proxy was written from scratch. We’re big fans of Node.js and AWS Lambda + API Gateway gave us the opportunity to develop in Node without worrying about the deployment and scaling.
How large was the team on this project? Did any/all of them have experience with Lambda already, or were they coming from other areas of expertise?
Spreaker has 4 engineers right now. I wrote the ad server proxy myself, and none of us had previous experience with AWS Lamda, but we have several years of production experience with both AWS and Node.js, so switching to Lambda wasn’t that difficult.
About how long did you spend developing the app? Was it any faster than if you were writing in another framework? (Express, Rails, whatever your "home turf" is)
The development took few weeks. Developing with AWS Lambda + API Gateway took out the complexity of managing/maintaining the deployment from server configuration to HA setup. This gave us the great benefit to focus on the business logic and let AWS doing their job: scaling your app from 1 request to millions.
How are you deploying the application?
The app is deployed using Grunt, based on two plugins: grunt-aws-lambda to deploy the Lambda functions and grunt-aws-apigateway to deploy API Gateway routes and mappings. The latter has been developed by me.
Are you using a CI/CD service? How does Lambda fit into that pipeline?
The app is fully tested, with both unit and functional tests. We use
mocha + chai to test it, and
mock-http-server to mock external services (ie. Triton ad server). We do
have a Jenkins setup, but this specific app isn’t currently part of our CI
What monitoring do you have in place? Is there anything you want to monitor but don't/can't yet?
We’re using CloudWatch logs and custom metrics to monitor the app.
How are you testing changes before they go to production? Do you have testing/staging environments?
Each application we build, including the ad server proxy, runs on three different environments.
- Local develepment
Most manual tests are done on our staging environment.
What kind of traffic have you been seeing since the app went live? Can you share how many pageviews/API hits the app is handling? Have you done any load testing to see what the limits are?
To give you a rough number, the Spreaker Podcast Radio app has more than 500K installs. Considering it does an ad request each time an audio track is played, you can easily do the math to get a rough volume amount.
Was there anything that surprised you along the way? Were certain tasks easier or harder than you'd expected?
Everything went smooth with AWS Lambda, but when it came to setup API Gateway we found it a bit annoying. If you use the web interface you’ve to do hundred of clicks, it’s error prone, and the documentation is not always clear. This is the main reason why I’ve written a grunt plugin to automize API Gateway deployment grunt-aws-apigateway.
Thanks to Marco, both for agreeing to be interviewed and for making a nice workflow for deploying API Gateway endpoints with Grunt. If you use Grunt for your node projects already, check out grunt-aws-apigateway to hook your code up to a hosted API endpoint.
Disclosure: I have no relationship to Spreaker, but they build cool stuff. And if you want to host a podcast, Spreaker has you well-covered.