When I started Tweet the Tube it was a small PHP application triggered by a cron job.

This had been fine for years, until I decided to ditch my hosting provider as it was costing me $20 per month.

I knew that I wanted to move into AWS, but running a nano EC2 instance would still cost me $5 per month. Not a lot of money but still more than I wanted to pay for such a small application.

Then I found out that AWS Lambda had a free tier. Better yet it meant no servers to manage. Seemed like a win-win to me!

I had heard of the Serverless Framework before and reading the documentation it seemed to make automation of Lambda deployment, scheduling and permissions a breeze.

In this day and age of cloud computing, being able to automate your infrastructure through code is really important. Serverless allows you to spin up and tear down your application with simple commands, keeping all of your infrastructure defined in config files.

As Serverless runs on Node.js it made sense for me to build my application the same way (Lambda currently supports Node.js, Java, C# and Python).

A couple of requirements I had for this project were that it should cost as little as possible to run and that I would need some sort of persistent storage to keep track of the different tube line statuses.

Here is what my serverless.yml file ended up looking like:

service: tweetthetube

provider:
  name: aws
  runtime: nodejs4.3
  stage: production
  region: eu-west-1
  memorySize: 128
  timeout: 30
  cfLogs: true
  iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:*
      Resource:
        - "arn:aws:s3:::tweetthetube-status"
        - "arn:aws:s3:::tweetthetube-status/*"

functions:
  cron:
    handler: handler.run
    events:
      - schedule: rate(5 minutes)

resources:
  Resources:
    CronLogGroup:
      Properties:
        RetentionInDays: "1"

Some interesting takeaways here. For start, I chose the smallest memory size of 128MB for the Lambda function. The whole application consumed much less than this and could run for 3.2 million seconds per month for free according to the pricing structure.

By default Serverless will create a Lambda function with 1024MB of memory, so make sure you adjust this if you don't need it and you'll get more time for the function to run for free.

Another default setting is the timeout of 6 seconds. If a function takes longer than this to run it will be stopped, so make sure you bump it up if you need more time.

The iamRoleStatements is an interesting one. Essentially it allows you to extend the permissions the Serverless user has to access other services on AWS. I chose S3 as the persistent storage mechanism for recording tube statuses, so I had to extend the permissions to get access to the S3 bucket.

A nice thing about Serverless is that it automatically configures the Lambda function to log output to CloudWatch and has useful commands to view these logs without going into the AWS console.

To keep the costs down however, I set the log retention time to 1 day through the resources section as by default they do not expire unless you manually delete them. It was a bit harder to figure out how to do this from within serverless.yml, however Serverless has a great community and my issue was quickly resolved on their Gitter channel.

The application itself was fairly easy to port over to Javascript. The asynchronous nature of the language meant that it was a challenge to build a synchronous application, however with the help of Bluebird I implemented Promises to avoid callback hell.

Overall I am really happy with how the application was built and how it run's on Lambda. It has better uptime and scalability potential than my original hosting provider. My only costs on AWS are for data transfer and storage on S3 which comes to $0.10 per month - a saving of $19.90. Happy days!