Scaling (Down) with AWS
Launching a new webapp is never easy - even one as simple as a URL shortener. Will it catch on? If it does, what does that mean in terms of traffic? 10, 100, 1000 requests per second?
A few weeks ago we did some back of the envelope calculations for how big wi.nr could get in the best case. The calculation went something like: 10,000 active users x 10 shortened URLs per day x 100 people clicking on each of those URLs = 10M shortened URLs clicked a day or ~120 per sec. For a variety of reasons, we use an AJAX request to actually check if the person viewing a link has won a prize. This can be a very intensive process - we need to take our official rules and check them against our database and logs (to prevent spammers and people trying to game the system). So we roughly tripled that estimate to ~400 per second. Add to that serving static content, the more expensive operations of viewing statistics for a link, actually shortening the URL, signing people in, sending emails to prize winners, now we’re at ~500 req/sec. Now, following the rule I use once I’ve come up with by best estimate for a job quote, web traffic or telling my wife how long I’ll be at the bar: double it - 1000 req/sec.
After a little benchmarking on my local machine (Core 2 Duo, 8GB of Memory, 10K RPM drives) and getting ~1500 req/sec - I decided better safe than sorry and launched a new EC2 Large instance running the Ubuntu Karmic Canonical AMI, installed all the necessary python libraries and applications and wi.nr was up and running at ~1200 req/sec - perfect.
The initial plan was to run the web server (Nginx), app server (Tornado) and DB server (MySQL with Percona patches) on the same instance. Easy setup, easy to manage and a clear path to scale up: split the DB off to another instance, serve static files and proxy the app server(s) from another instance and run as many instances as needed for the app server.
After days of reading about RAID arrays across EBS volumes and performance optimizations for running MySQL on EC2, Amazon comes to the rescue and does it all for me - enter Amazon Relational Data Store. I downloaded the RDS CLI tools and a few commands later and I’ve got MySQL up and running and the wi.nr app connecting to a small RDS instance, churning out ~1500 req/sec. Not bad.
We launched wi.nr a couple weeks ago with a good amount of initial adoption and steadily growing traffic. The numbers we came up with in our earlier calculations are still a ways off, but we were seeing some nice traffic spikes coinciding with some popular twitter users mentioning us. Then we got our first statement from AWS, and a few more back-of-the-envelope calculations later and we realized that our grandiose dreams of making millions thousands hundreds dozens of dollars from our URL shortener were going to be hard to achieve. This is not to say that our bill from Amazon was unexpected or large by any means - we’re still a month away from our Amazon bills matching the setup fee at a local COLO I’ve had my eye on.
I looked back at the cloudwatch monitoring for the last few weeks and saw a flatline for CPU utilization at just over 0%. The decision to scale back our EC2 Large instance was a pretty obvious one. Our traffic is growing in a fairly steady manner, and our best case scenario of 1000 req/sec is more than a couple orders of magnitude away.
This morning, I fired up a small instance with the 32 bit version of the Karmic AMI, did a dpkg —get-selections on the large instance, a dpkg —set-selections and apt-get dselect-upgrade on the small instance, fired up a new EBS volume from a snapshot of the existing one, rsync’d some configuration to the new instance and remapped the elastic IP - less than 30 minutes later and we’re saving $185 a month and still able to handle ~400 requests per second.
Before spinning down the Large instance, I created a private AMI of the running instance. If wi.nr goes gangbusters, I can probably get traffic hitting a large instance in less than a couple minutes.
So there’s the story of my first experience with AWS and the birth of wi.nr.
— Tom
For all the geeks out there
We’ve discussed wi.nr with a few entrepreneurs and one of the first questions we get is “how was it built?” So we thought we’d provide a nice rundown of the platforms we’ve used, as well as give out some props:
winr is written in python and built on the Tornado Framework which provides all sorts of goodies like OAuth authentication and a screaming fast asynchronous web server out of the box.
winr is hosted on Amazon Web Services: We make use of Elastic Compute Cloud and Relational Database Service in particular.
We’re using the Google Visualization API to draw pretty graphs for statistics, the excellent Chunk Font from The League of Moveable Type. We’re also using the beautiful Helveticons and Silk Icons in a few places.
Props!
Welcome to winr, the url shortener that can win you stuff.
Last week we quietly launched winr, a new URL shortener that gives away free prizes.
Here’s the lowdown on our project:
There are quite a few url shorteners in the marketplace; many that offer the same features (or lack thereof). But we felt that room for innovation still existed. Tom, our lead developer, built a URL shortener in his spare time, and we spent some time thinking about how we could release the url shortener to offer a unique experience that would drive user adoption.
In a space where competitors with significant market share (bit.ly) and barriers to entry (Twitter client integration) exist, what can you do to make an impact and carve out a niche?
We thought about how companies were using sweepstakes and giveaways as a social media marketing tool on Twitter, and how a Twitter sweepstakes subculture has developed as a result.
Why not a URL shortener that enters its users to win prizes? It sounded like a fun idea. So we built it.
You can win prizes by shortening urls with winr, clicking on wi.nr urls, or by referring people. So for every win triggered in our system, a total of three prizes can be given out: One for the shortener, one for the clicker, and one for the referrer. Good stuff.
So use wi.nr. Our URLs are really short. And you can win prizes too!
Use winr as your default URL shortener with Tweetie for iPhone
Tweetie 2, the excellent iPhone app for Twitter, allows you to use a custom short URL provider. Here are some quick instructions on how to set that up using winr:
- First, you need your winr API key. That way any short URLs you create with Tweetie are linked with your winr account. Just go to http://wi.nr/api/ to retrieve your API key.
- In Tweetie’s settings, navigate to:
“URL Shortening > Custom…” - In the text box that pops up, type this URL:
http://wi.nr/api/shorten?url=%@&api_key=YOUR-API-KEY-GOES-HERE
Make sure to replace “YOUR-API-KEY-GOES-HERE” with your API key.
That’s it!

