The serverless world is pretty awesome once you find the right tools — and burn the middle layer to the ground
After the tour-de-force of Serverlessconf in October, I decided my entire company would be going serverless. I spent the first couple of months beating my head against the wall trying to migrate a Python Flask app to Lambda — these efforts helped me find a better way.
The fear and frustration of migrating a simple web app to serverless — I spent the weekend fighting functions while trying to move a Flask application hosted on Elastic Beanstalk to AWS — read.acloud.guru
Six months later, we are now deploying our fourth major project serverlessly. This is how we did it — including the lessons learned (and strong opinions) formed along the way.
Lesson #1 — Ditch Python
Flask is a nice little framework for the old-time request-response style of a website with a session managed by the server. That’s quaint — but in the new world of the interactive web, it’s like trying to build a house with a rubber band and a squeegee.
Increasingly, Flask solutions become a kluge of different languages. I concluded fairly quickly that this approach was a horrific mess — and I wasn’t sure why I was using Python anymore.
Lesson #2 — Burn the middle layer to the ground
It took us a surprising amount of time to realize an obvious benefit of serverless — possibly because we’ve been building web apps forever, or maybe it’s just that I’m getting old.
Some of our first web apps still had a Node Express layer that remembered session state either (1) by accident hoping the user hit the same Lambda container over and over, or (2) by tragedy of design where we abused DynamoDB to make it remember session IDs. What the hell were we doing?
Lesson #3 — Enjoy the Vue
It’s great being able to jam everything into the front-end, but it’s quickly an appalling mess. You eventually stop checking in code because you’re too embarrassed to share the Rube Goldberg machine magic you’ve been building. And ‘not checking in code’ is not a good job objective for developers.
Entering the world of Single Page Applications (SPAs) exposed me to React — the most popular approach to building user interfaces. React is great but comes with a steep learning curve, lots of Webpack/Babel set up, and the introduction of JSX. While it might be something we eventually use, it was too heavyweight for our immediate needs so explore the alternatives.
Fortunately, I soon discovered Vue.js and my serverless life turn to absolute bliss. Here’s the thing: You can learn Vue in a day!
Vue’s approach to design fits nicely with our design model — everything is a component that manages its own content, design and code. This makes it very easy to manage our multiple client-projects and dispersed teams, and also work very well for a serverless mindset.
From a serverless perspective, Vue compiles all your goodness into an index.html and bundle.js files, primed for uploading to S3. Typing
npm run build is the new compile command.
Take a moment to consider this — in the old world, we would be deploying apps via Elastic Beanstalk and monitoring for utilization, autoscaling when needed, and managing a reasonable chunk of infrastructure.
The true magic of SPAs is when you “deploy” an application, you’re simply copying index.html, bundle.js, and a handful of file dependencies to an S3 bucket front-ended by a CloudFront distribution. This gives you rock-steady distribution and loading behavior, and also enables multi-version management and any deployment methodology you prefer — just by managing text files.
We have effectively unlimited scale and only pay for what we use — there is zero app infrastructure management.
Vue essentially allows you to build a desktop application within the browser — which means you can dramatically improve the user experience. All the state can be managed here without endless request/response, you can hide latency with standard UI tricks like transition effects, and the whole application now behaves properly.
Lesson #4 — Learn to love DynamoDB
In many respects, the hardest part of getting to serverless has been truly coming to grips with DynamoDB. You definitely make a few mistakes in the first few iterations, and its tempting to ditch the whole thing and go back to RDS where everything is known and comfortable.
SQL has been my crutch for a long time, and I’ll confess to putting way too much business logic into databases. But RDMS systems are just another monolith — failing to scale well and they don’t support the idea of organically evolving agile systems.
DynamoDB is a completely different animal. When you get it right, the NoSQL database provides blistering performance, massive scale, and practically no administrative overhead. But you really have to invest the time in exploring how it works — and the initial phases are full of gotchas aplenty.
Dynamo table fields can’t contain empty strings. The point in time backup isn’t automatic. If you get the partition and sort keys wrong, you have to start from scratch with your tables. You can go from having too few tables to way too many if you try to emulate SQL queries too closely. And all the while it just feels very alien coming from RDS.
After many tutorials, trying, failing and eventually succeeding with DynamoDB, I learned …
- You need to understand the way DynamoDB works, spend some time to understand indexing strategies, and how you intend to query the data. It’s very easy to jump into it without knowing all you need to know, so many people get burned and then move back to RDMS at exactly the wrong moment. Make mistakes and push through them.
- One of the least-discussed joys of DynamoDB is the way you can attach code to table events using streams — like an SQL trigger that can do anything. These are extremely powerful. A very simple pattern we use is to always push table updates to an SNS topic where the changes can be ingested by other serverless code you might not have written yet.
- Don’t forget that DynamoDB can feed other storage systems (RDMS, Redshift or just flat text files) and can be used to effectively smooth out the traffic spikes or protect another database from huge volumes of data. DynamoDB has a TTL feature which allows you to expire rows — which is great for staging data you want to push somewhere else.
Lesson #5 — Serverless Framework FTW
My early experimentation with Lambda was a clunky affair of coding directly into the AWS console and getting frustrated that it took a lot of work and error messages to do some trivial things. The bridge that connects your IDE to a production environment is missing.
Well, its’ missing until you discover serverless framework which is honestly the most exciting thing I’ve found in ages.
sls deploy wields enormous power, bundling up your precious code and shipping it directly to Amazon’s brain in the sky. And if you need to check logs because your code is misbehaving just type
sls logs -f functionname -t and you can tail your CloudWatch logs like a pro without ever opening a browser.
This. Changes. Everything. The serverless people should be showered with accolades for doing something that every cloud provider should have offered from day one. Simply brilliant. And so much win.
Asked about impact of serverless. Gosh, it’s rather simple. Entirely new set of emerging practices that’ll change the way we build business.— Simon Wardley (@swardley) November 18, 2016
Lesson #6 — Authorization is the new sheriff in town
In traditional apps, you authenticate a user once and then track this person by following around a session ID. We like it because you only need to do the hard work once, and then the ID lets you cheat for the lifetime of the user’s login for however long you want that to be.
But this approach has problems. It only works if you have that server in the middle — and we we just burned that server to the ground. It also potentially exposes you to some nasty attacks — like Cross-Site Request Forgeries (CSRF) — and doesn’t let you pass around identity to other services very easily. So this approach basically Supports The Monolith (boooo!).
We hate the Monolith and CSRF attacks — but we do like our new friend, the JWT token. I had a moment of zen-like euphoria when I learned how this works but I need a diagram to do it justice.
Step 1, get a JWT, step 2, use it to communicate with any service you write:
The basic nut is that every single request is authenticated, and the client can even talk to multiple serverless activities. It’s wickedly secure, it’s anti-monolith and CSRF doesn’t even exist in JWT-land. All that’s required from your serverless code is use a Custom Authorizer to check if the JWT in the header is valid (using boilerplate code) and we are done.
JWT makes all other types of auth look overcomplicated. We switched everything to Auth0 (and Cognito in some cases) and never looked back. Serverless auth is both beguilingly simple and insanely effective, so yeah, go team.
It’s a brave new world
While I’ve worked with AWS for a long time, I’ve never been this close to the ground floor. Even in EC2 land, there was plenty of help because I was comparatively late to the party. After leaving A Cloud Guru’s serverless conference, this felt like genuinely unexplored territory and there was significantly more discovery in the dark.
JUST ANNOUNCED…— Serverlessconf (@Serverlessconf) April 23, 2018
Serverlessconf is headed to San Francisco, CA from July 29 – August 1, 2018! Be sure to take advantage of early-bird pricing by registering through our site, https://t.co/vSkgMJUsPK. Stay tuned for our sponsor and speaker ‘shout outs’! pic.twitter.com/agjqydSN1E
In our first few experiments, we had some misfires trying to use existing tools and techniques — and the results weren’t great. After a few months getting the right stack in place, we have officially started delivering projects in a 100% serverless way. I’m confident that our migration hiccups and early exploring were well worth the journey.
We are building slick, real-time SPA apps that use exclusively serverless infrastructure, scale effortlessly and cost 70–90% less. I’m both delighted and shocked by the payoff. I’ve never been more convinced that serverless tech is going to revolutionize application delivery in the cloud.
The results are transformational.