Serverless
The pros and cons of building a company
without infrastructure
Luciano Mammino

1 June 2017, Split
Who is LUCIANO


NeBK20FUA
-20% eBook
NpBK15FUA
-15% Print
fancy a coupon? π
</ shameless-self-promotion >
Agenda
What is Serverless
History & definition
Advantages & costs
How it Works
Example: AWS Lambda
Example: Serverless Framework
Serverless at Planet 9
Architecture
Security
Quality
Monitoring / Logging
Step Functions
PART 1
What is Serverless
1996 - Let's order few more servers for this rack...

2006 - Let's move the infrastructure in "the cloud"...

2013 - I can "ship" the new API to any VPS as a "container"

TODAY - I ain't got no infrastructure, just code "in the cloud" baby!


The essence of the serverless trend is the absence of the server concept during software development.
β Auth0


Serverless & Serverless.com Framework
π¨βπ» Focus on business logic, not on infrastructure
π Virtually βinfiniteβ auto-scaling
π° Pay for invocation / processing time
Advantages of serverless
Is it cheaper to go serverless?
... It depends
Car analogy
Cars are parked 95% of the time (loige.link/car-parked-95)
How much do you use the car?

Own a car
(Bare metal servers)

Rent a car
(VPS)

City car-sharing
(Serverless)

Less than $0.40/day
for 1 execution/second
What can we build?
π± Mobile Backends
π APIs & Microservices
π¦ Data Processing pipelines
β‘οΈ Webhooks
π€ Bots and integrations
βοΈ IoT Backends
π» Single page web applications
The paradigm
Event β π
IF ________________________________ THEN ________________________________
"IF this THEN that" model
A new CSV file is saved in the object storage
Process it and save it in the DB
HTTP request: GET /products
Retrieve products from DB and return a JSON
It's 2 AM
Scrape weather forecast for next days
Cloud providers
IBM
OpenWhisk
AWS
Lambda
Azure
Functions
Cloud Functions
Auth0
Webtask
Serverless and JavaScript
Frontend
π Serverless Web hosting is static, but you can build SPAs
(React, Angular, Vue, etc.)
Backend
π Node.js is supported by every provider
β‘οΈ Fast startup (as opposed to Java)
π¦ Use all the modules on NPM
π€ Support other languages/dialects
(TypeScript, ClojureScript, ESNext...)
exports.myLambda = function (
event,
context,
callback
) {
// get input from event and context
// use callback to return output or errors
}
Anatomy of a Node.js lambda on AWS
Let's build a "useful"
Hello World API






// write code here
'use strict'
exports.helloWorldHandler = (event, context, callback) => {
const name =
(event.queryStringParameters && event.queryStringParameters.name) ?
event.queryStringParameters.name : 'Split';
const response = {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({message: `Hello ${name}`})
};
callback(null, response);
};


π€

API Gateway config has been generated for us...

Recap
-
Login to AWS Dashboard
-
Create new Lambda from blueprint
-
Configure API Gateway trigger
-
Configure Lambda and Security
-
Write Lambda code
-
Configure Roles & Publish
β‘οΈReady!
No local testing πͺ ... Manual process π«
Enter the...


Get serverless framework
npm install --global serverless@latest
sls --help
Create a project
mkdir helloWorldApi
cd helloWorldApi
touch handler.js serverless.yml
// handler.js
'use strict';
exports.helloWorldHandler = (event, context, callback) => {
const name =
(event.queryStringParameters && event.queryStringParameters.name) ?
event.queryStringParameters.name : 'Split';
const response = {
statusCode: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({message: `Hello ${name}`})
};
callback(null, response);
};
# serverless.yml
service: sls-helloWorldApi
provider:
name: aws
runtime: "nodejs6.10"
functions:
helloWorld:
handler: "handler.helloWorldHandler"
events:
- http:
path: /
method: get
Local test
touch event.json
{
"queryStringParameters": {
"name": "Tim Wagner"
},
"httpMethod": "GET",
"path": "/"
}
Local test

Deploy the lambda

Recap
-
Install serverless framework
-
Create handler & serverless config
-
Test locally (optional)
-
Deploy
-
Party hard! π€
PART 2
Serverless at Planet 9

a Big Data company
E.g. Meter readings per customer/year
2 Γ 24 Γ 365
Half Hours
Γ 25
~ meter reading points
Γ 24
~ data versions
= π©loadβ’
of data
π©βπ Limited number of βFull stackβ engineers
β‘οΈ Write & deploy quality code fast
π» Experiment different approaches over different features
π Adopt hot and relevant technologies
Limited number of servers = LIMITED CALLS AT 2 AM!
Why Serverless
Current infrastructure
Serverless land











Web
API & Jobs
Messaging
Serverless
Frontend & Backend




Cloufront & S3
API Gateway & Lambda
planet9energy.io
api.planet9energy.io
Access-Control-Allow-Origin: https://planet9energy.io
CORS HTTP HEADER
Custom error page
index.html
Serverless Web Hosting
Serverless APIs
Security: Authentication
"Who is the current user?"

JWT Tokens
Custom
Authorizer Lambda


JWT Token
Authorizer
Login
user: "Podge" pass: "Unicorns<3"

Users DB
Check
Credentials
JWT token
Validate token & extract userId
API request

API 1

API 2

API 3
Security: Authorization
"Can Podge trade for Account17 ?"
User
Action
Resource
User |
Action |
Resource |
---|---|---|
Podge |
trade |
Account17 |
Podge |
changeSettings |
Account17 |
Luciano |
delete |
* |
... |
... |
... |
import { can } from '@planet9/acl';
export const tradingHandler =
async (event, context, callback) => {
const user = event.requestContext.userId;
const account = event.pathParameters.accountId;
const isAuthorized = await can(user, 'trade', account);
if (!isAuthorized) {
return callback(new Error('Not Authorized'));
}
// ... business logic
}
Security: Sensitive Data

export const handler = (event, context, callback) => {
const CONN_STRING = process.env.CONN_STRING;
// ...
}
# serverless.yml
functions:
myLambda:
handler: handler.myHandler
environment:
CONN_STRING: ${env:CONN_STRING}

Serverless environment variables

Split business logic into small testable modules
Use dependency injection for external resources
(DB, Filesystem, etc.)-
Mock stuff with Jest
Aim for 100% coverage
Nyan Cat test runners! πΌ
Quality: Unit Tests
Use child_process.exec to launch "sls invoke local"
Make assertions on the JSON output
Test environment simulated with Docker (Postgres, Cassandra, etc.)
Some services are hard to test locally (SNS, SQS, S3)
Quality: Functional Tests
π¨ Git-Flow
Feature branches
-
Push code
GitHub -> CI
Quality: Continuous integration
π€ CircleCI
-
Lint code (ESlint)
-
Unit tests
-
Build project
-
Functional tests
-
if commit on "master": create deployable artifact

Development / Test / Deployment
Debugging

... How do we debug then
-
console.log... π
-
Using the debug module
-
Enable detailed logs only when needed
(e.g. export DEBUG=tradingCalculations)

Step Functions
Coordinate components of distributed applications
Orchestrate different AWS Lambdas
Visual flows
Different execution patterns (sequential, branching, parallel)




Some lessons learned...
π Think serverless as microservices "microfunctions"
βοΈ Cold starts!
π« Be aware of soft limits
π There is still some infrastructure: use proper tools
(Cloudformation, Terraform, ...)
π PROs
π
Agility
π
Focus on delivering
Business Value
π
Auto-scalability
π
Managed service
No calls at 2 am...
π
Smooth
Learning Curve
π
Pay as you go!
π CONs
π
No live debugging
π
Local development & testing
π
Service/Functions
Orchestration
π
Servers are still there
π
lacking
Tooling / Best practices
Should I switch to
SERVERLESS ? π±
Thanks

(special thanks to @katavic_d, @Podgeypoos79, @quasi_modal & @augeva)