SlideShare a Scribd company logo
ServerlessServerless
The "Middy" wayThe "Middy" way
—
Workshop
   loige.link/middy-way
Community Day Dublin
October , 1st 2019
Luciano Mammino
@loige
Wi-Fi:
DC_Conference
October-2019
1
2
Hello, I am Luciano!Hello, I am Luciano!
2
Hello, I am Luciano!Hello, I am Luciano!
2
Hello, I am Luciano!Hello, I am Luciano!
2
Hello, I am Luciano!Hello, I am Luciano!
2
Hello, I am Luciano!Hello, I am Luciano!
Cloud Architect
2
Hello, I am Luciano!Hello, I am Luciano!
Cloud Architect
Blog:
Twitter:
GitHub:  
loige.co
@loige
@lmammino
2
Hello, I am Luciano!Hello, I am Luciano!
Cloud Architect
Blog:
Twitter:
GitHub:  
loige.co
@loige
@lmammino
2
Hello, I am Luciano!Hello, I am Luciano!
Cloud Architect
Blog:
Twitter:
GitHub:  
loige.co
@loige
@lmammino
2
loige.link/middy-wayloige.link/middy-way
@loige 3
Let's chat on:Let's chat on:
tlk.io/middy-waytlk.io/middy-way
@loige 4
What is serverlessWhat is serverless
Compute as functions (FaaS)Compute as functions (FaaS)
Event-based modelEvent-based model
@loige 5
Why serverless is goodWhy serverless is good
Focus on business logicFocus on business logic
ScalabilityScalability
Pay per usage model (compute time * memory)Pay per usage model (compute time * memory)
Managed infrastructureManaged infrastructure
Forces you to think micro-servicesForces you to think micro-services
@loige 6
My Serverless experienceMy Serverless experience
Open source
A semi-automated weekly newsletter ( )
A middleware framework for AWS Lambda ( )
Enterprise
Trading, Billing engine, Market data aggregator solutions ( )
Big data pipeline to make network metadata searchable ( )
Organised various workshops around Europe ( )
Fullstack bulletin
middy.js.org
ESB
Vectra.ai
Serverlesslab.com
@loige 7
Let's get this party startedLet's get this party started
@loige 8
Requirements!Requirements!
♂ ♂ 
@loige 9
A nice laptopA nice laptop
@loige 10
An AWS accountAn AWS account
  
aws.amazon.com/freeaws.amazon.com/free
@loige 11
Have anHave an admin useradmin user
in your AWS accountin your AWS account
  
loige.link/aws-admin-userloige.link/aws-admin-user
@loige 12
install the AWS CLIinstall the AWS CLI
  
aws.amazon.com/cliaws.amazon.com/cli
@loige 13
configure the AWS CLIconfigure the AWS CLI
  
loige.link/aws-cli-configloige.link/aws-cli-config
@loige 14
VerifyVerify
aws sts get-caller-identity
{
"Account": "123456789012",
"UserId": "ABCDEFGHIJKLMNOPQRSTU",
"Arn": "arn:aws:iam::123456789012:user/super-mario"
}
@loige 15
Install Git and Node.jsInstall Git and Node.js
  
git-scm.comgit-scm.com
nodejs.orgnodejs.org  
@loige 16
You are ready!You are ready!
@loige 17
What are we going to build?What are we going to build?
@loige 18
@loige
A realtime dashboard for public transport!A realtime dashboard for public transport!
19
loige.link/middy-way-starterloige.link/middy-way-starter
Read... the README!
Clone the project locally
Deploy it to your AWS account
Play with the APIs
@loige 20
loige.link/middy-way-starterloige.link/middy-way-starter
Read... the README!
Clone the project locally
Deploy it to your AWS account
Play with the APIs
I need staaarz!
@loige 20
⏱ 20 mins warm up ♀ ⏱ 20 mins warm up ♀ 
1. Use the APIs to create a dashboard that contains:1. Use the APIs to create a dashboard that contains:
An IrishRail station widget
A LUAS stop widget
A DublinBus stop widget
(there are utility scripts to list all the stops and stations, check the README)
 
2. Have a look at the code2. Have a look at the code
If you find bugs, please send a or report anPR issue
@loige 21
AWS Lambda & MiddyAWS Lambda & Middy
❤❤
@loige 22
The problem with LambdasThe problem with Lambdas
@loige 23
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 AWSAnatomy of a Node.js lambda on AWS
@loige 24
(event, context, callback) => {
// decrypt environment variables with KMS
// deserialize the content of the event
// validate input, authentication, authorization
// REAL BUSINESS LOGIC
// (process input, generate output)
// validate output
// serialize response
// handle errors
}
A typical "REAL" Lambda functionA typical "REAL" Lambda function
@loige 25
(event, context, callback) => {
// decrypt environment variables with KMS
// deserialize the content of the event
// validate input, authentication, authorization
// REAL BUSINESS LOGIC
// (process input, generate output)
// validate output
// serialize response
// handle errors
}
A typical "REAL" Lambda functionA typical "REAL" Lambda function
@loige 25
(event, context, callback) => {
// decrypt environment variables with KMS
// deserialize the content of the event
// validate input, authentication, authorization
// REAL BUSINESS LOGIC
// (process input, generate output)
// validate output
// serialize response
// handle errors
}
A typical "REAL" Lambda functionA typical "REAL" Lambda function
@loige 25
(event, context, callback) => {
// decrypt environment variables with KMS
// deserialize the content of the event
// validate input, authentication, authorization
// REAL BUSINESS LOGIC
// (process input, generate output)
// validate output
// serialize response
// handle errors
}
A typical "REAL" Lambda functionA typical "REAL" Lambda function
LOTS of BOILERPLATE
@loige 25
The solutionThe solution
@loige 26
npm install @middy/core
Note: using preview (alpha)version 1.0.0
@loige 27
npm install @middy/core
Note: using preview (alpha)version 1.0.0
Give it moar love
@loige 27
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = (event, context, callback) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
@loige
28
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = (event, context, callback) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
1. define handler
@loige
28
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = (event, context, callback) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
2. "middify"  the handler
@loige
28
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = (event, context, callback) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
3. attach middlewares
@loige
28
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = (event, context, callback) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler } 4. export "middyfied" handler
@loige
28
const middy = require('@middy/core')
const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser')
const validator = require('@middy/validator')
const httpErrorHandler = require('@middy/http-error-handler')
const processPaymentHandler = (event, context, callback) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return callback(null,
{ result: 'success', message: 'payment processed correctly'}
)
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler }
@loige
29
const middy = require('@middy/core')
const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser')
const validator = require('@middy/validator')
const httpErrorHandler = require('@middy/http-error-handler')
const processPaymentHandler = (event, context, callback) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return callback(null,
{ result: 'success', message: 'payment processed correctly'}
)
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler }
Handler
@loige
29
const middy = require('@middy/core')
const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser')
const validator = require('@middy/validator')
const httpErrorHandler = require('@middy/http-error-handler')
const processPaymentHandler = (event, context, callback) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return callback(null,
{ result: 'success', message: 'payment processed correctly'}
)
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler }
Attach middlewares
@loige
29
const middy = require('@middy/core')
const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser')
const validator = require('@middy/validator')
const httpErrorHandler = require('@middy/http-error-handler')
const processPaymentHandler = (event, context, callback) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return callback(null,
{ result: 'success', message: 'payment processed correctly'}
)
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler } Export enhanced handler
@loige
29
Why?Why?
@loige 30
Why?Why?
Simplify code
@loige 30
Why?Why?
Simplify code
Reusability
input parsing
input & output validation
output serialization
error handling
...
@loige 30
Why?Why?
Simplify code
Reusability
input parsing
input & output validation
output serialization
error handling
...
Focus (even) MORE on business logic@loige 30
How it worksHow it works
@loige 31
Execution orderExecution order
32@loige
Execution orderExecution order
32@loige
Execution orderExecution order
1. middleware1 (before)
32@loige
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
32@loige
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
32@loige
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
32@loige
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
32@loige
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
6. middleware2 (after)
32@loige
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
6. middleware2 (after)
7. middleware1 (after)
32@loige
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
6. middleware2 (after)
7. middleware1 (after)
32@loige
When an error happens...When an error happens...
Flow is stopped
First middleware implementing `onError` gets control
It can choose to handle the error, or delegate it to the next handler
If the error is handler a response is returned
If the error is not handled the execution fails reporting the unhandled error
@loige 33
Writing a middlewareWriting a middleware
const myMiddleware = (config) => {
// might set default options in config
return ({
before: (handler, next) => {
// might read options from `config`
},
after: (handler, next) => {
// might read options from `config`
},
onError: (handler, next) => {
// might read options from `config`
}
})
}
module.exports = myMiddleware
@loige
34
Inline middlewaresInline middlewares
const middy = require('@middy/core')
const handler = middy((event, context, callback) => {
// do stuff
})
handler.before((handler, next) => {
// do something in the before phase
next()
})
handler.after((handler, next) => {
// do something in the after phase
next()
})
handler.onError((handler, next) => {
// do something in the on error phase
next()
})
module.exports = { handler }
@loige
35
It supports async handlers!It supports async handlers!
const middy = require('@middy/core')
const handler = middy(
async (event, context) => {
// do stuff
return { some: 'response' }
}
)
module.exports = { handler }
@loige
36
Exercise 0Exercise 0: let's middify!: let's middify!
In the next exercises we will need the full power of middy, so to get started let's
just "middify" all our handlers
—
Note: handlers are defined in "src/handlers", and they get used in
"src/handler.js". You can either middify every single handler file or middify them
when used in src/handler.js. In the first case, make sure you middify the actual
handler function and not the "handler factory".
 
( )a solution
@loige 37
Exercise 1Exercise 1: body parsing: body parsing
We are manually deserializing the JSON input in our APIs.
We can simplify the code a bit by using the middleware.
—
 
Install @middy/http-json-body-parser and remove all the instances of
JSON.parse() in our handlers.
 
( )
http-json-body-parser
a solution
@loige 38
What happens when one of our handlers crashes? We are actually not even
dealing with errors right now... by using the  middleware we
will be able to handle all HTTP errors and return codes consistently.
—
 
Install @middy/http-error-handler and apply that to all our handlers.
 
( )
http-error-handler
a solution
Exercise 2Exercise 2: what if we fail?: what if we fail?
@loige 39
We want to make sure that data is validated before being written to the
database. We can use the middleware for this task!
—
Install @middy/validator and apply that to all our POST API handlers. You can
use  to define your schemas or, if you are struggling, you can
find some schemas ready-made for you  :)
 
Note: The validator should be added after the json-body-parser, so you can
validate individual fields of the input data.
 
( )
validator
jsonschema.net
here
a solution
Exercise 3Exercise 3: validate!: validate!
@loige 40
We have our dashboards fully working, but consuming them in JSON is definitely
not the friendliest experience! It would be much better to do in a properly
rendered HTML so that we could easily visualize them on our mobile device!
—
You can implement this in (at least) 2 ways :
Using the middleware and building a frontend somewhere like
or
Using the middleware and implementing a
specific rule for accept "text/html"
 
( - )
http-cors
codesandbox codepen
http-content-negotiation
a CORS solution a CodeSandbox React UI
Exercise 4Exercise 4: mobile rendering: mobile rendering
@loige 41
Did you notice that our APIs are fully open? Knowing the endpoint and the id,
anyone can basically change or delete the dashboards! That's unacceptable!
—
Find a way to secure the APIs.
One easy way could be to create a secret random token when a dashboard is
created the first time. Then you can create a custom middleware that checks
the secret every time someone is trying to modify or delete that dashboard!
 
Note: if you feel fancy you can use JWT tokens, in such case you could take
inspiration from the middleware!jwt-auth
Exercise 5Exercise 5: better safe than sorry: better safe than sorry
@loige 42
Sometimes our APIs are very slow. They take literally seconds to answer. This is
because of a common serverless issue known as " ". If you are
running for your train every morning, this is unacceptable! We should fix this...
—
 
Use the  middleware to mitigate the cold start issue
 
Note: make sure to also setup the proper event for every API. 
cold start problem
warmup
schedule
2
@loige
Exercise 6Exercise 6: stop the cold!: stop the cold!
43
Some of your Java friends would love to use these APIs to build a shiny SWING
UI... The problem is that they don't really like JSON and they would rather have a
good old XML-based API. You might think that this is actually their problem, but
also, you don't want to lose your friends...
—
 
Use the  middleware to provide responses in XML for
accept "application/xml".
 
Note: You could use a library like  to automate the conversion of
JavaScript objects to XML.
http-content-negotiation
json2xml
@loige
Exercise 7Exercise 7: legacy friendship: legacy friendship
44
In summaryIn summary
Serverless is cool, it helps you to build apps quickly and with a greater
focus on business logic, rather than on infrastructure!
Middy helps you to keep focusing on your business logic first
You can add extra behaviours with very minimal changes to your core
logic by introducing dedicated middlewares
You can easily share common functionality through middlewares
45
If you like MiddyIf you like Middy
Use itUse it
Give feedbackGive feedback
Contribute (I am looking for co-maintainers)Contribute (I am looking for co-maintainers)
Version 1.0 (stable) coming soonVersion 1.0 (stable) coming soon
46
Thank youThank you
@loige 47
CreditsCredits
Cover Image by  from
 
A special thank you to all the amazing Middy users
and !
 
Thanks to for reviewing these
slides and to  for finding lots of bugs!
TotumRevolutum Pixabay
contributors
@StefanoAbalsamo
@organicdelight
@loige 48

More Related Content

What's hot

Keycloakの動向
Keycloakの動向Keycloakの動向
Keycloakの動向
Yuichi Nakamura
 
Drone sdk showdown
Drone sdk showdownDrone sdk showdown
Drone sdk showdown
Godfrey Nolan
 
Sharepoint 2010 User Stories
Sharepoint 2010 User StoriesSharepoint 2010 User Stories
Sharepoint 2010 User Stories
Shuffle IT Solutions
 
Javascript で暗号化
Javascript で暗号化Javascript で暗号化
Javascript で暗号化
suno88
 
ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~
ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~
ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~
Hiroshi Tokumaru
 
Streams in Node.js
Streams in Node.jsStreams in Node.js
Streams in Node.js
Sebastian Springer
 
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumaiクリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
Shohei Okada
 
Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python
Jean Carlo Machado
 
Redmine 4.0 の新機能、Redmine 4.1の開発状況
Redmine 4.0 の新機能、Redmine 4.1の開発状況Redmine 4.0 の新機能、Redmine 4.1の開発状況
Redmine 4.0 の新機能、Redmine 4.1の開発状況
Go Maeda
 
git - eine praktische Einführung
git - eine praktische Einführunggit - eine praktische Einführung
git - eine praktische Einführung
Marcel Eichner
 
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
koji lin
 
Git Grundlagen
Git GrundlagenGit Grundlagen
Git Grundlagen
Benjamin Schürmann
 
Spring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjugSpring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjug
Masatoshi Tada
 
Gitlab Training with GIT and SourceTree
Gitlab Training with GIT and SourceTreeGitlab Training with GIT and SourceTree
Gitlab Training with GIT and SourceTree
Teerapat Khunpech
 
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
Masatoshi Tada
 
Entities on Node.JS
Entities on Node.JSEntities on Node.JS
Entities on Node.JS
Thanos Polychronakis
 
GitHub Actions in action
GitHub Actions in actionGitHub Actions in action
GitHub Actions in action
Oleksii Holub
 

What's hot (17)

Keycloakの動向
Keycloakの動向Keycloakの動向
Keycloakの動向
 
Drone sdk showdown
Drone sdk showdownDrone sdk showdown
Drone sdk showdown
 
Sharepoint 2010 User Stories
Sharepoint 2010 User StoriesSharepoint 2010 User Stories
Sharepoint 2010 User Stories
 
Javascript で暗号化
Javascript で暗号化Javascript で暗号化
Javascript で暗号化
 
ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~
ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~
ここが変だよ、グローバルスタンダードの脆弱性対策~入力値の考え方~
 
Streams in Node.js
Streams in Node.jsStreams in Node.js
Streams in Node.js
 
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumaiクリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
クリーンアーキテクチャの考え方にもとづく Laravel との付き合い方 #shuuumai
 
Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python Domain Driven Design Made Functional with Python
Domain Driven Design Made Functional with Python
 
Redmine 4.0 の新機能、Redmine 4.1の開発状況
Redmine 4.0 の新機能、Redmine 4.1の開発状況Redmine 4.0 の新機能、Redmine 4.1の開発状況
Redmine 4.0 の新機能、Redmine 4.1の開発状況
 
git - eine praktische Einführung
git - eine praktische Einführunggit - eine praktische Einführung
git - eine praktische Einführung
 
サーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよサーバーサイドでの非同期処理で色々やったよ
サーバーサイドでの非同期処理で色々やったよ
 
Git Grundlagen
Git GrundlagenGit Grundlagen
Git Grundlagen
 
Spring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjugSpring Bootの本当の理解ポイント #jjug
Spring Bootの本当の理解ポイント #jjug
 
Gitlab Training with GIT and SourceTree
Gitlab Training with GIT and SourceTreeGitlab Training with GIT and SourceTree
Gitlab Training with GIT and SourceTree
 
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
ReactiveだけじゃないSpring 5 & Spring Boot 2新機能解説
 
Entities on Node.JS
Entities on Node.JSEntities on Node.JS
Entities on Node.JS
 
GitHub Actions in action
GitHub Actions in actionGitHub Actions in action
GitHub Actions in action
 

Similar to Serverless, The Middy Way - Workshop

Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​ Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​
Luciano Mammino
 
Serverless and React
Serverless and ReactServerless and React
Serverless and React
Marina Miranovich
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
Jose Manuel Pereira Garcia
 
Socket applications
Socket applicationsSocket applications
Socket applicationsJoão Moura
 
Building Serverless applications with Python
Building Serverless applications with PythonBuilding Serverless applications with Python
Building Serverless applications with Python
Andrii Soldatenko
 
Automatisation in development and testing - within budget
Automatisation in development and testing - within budgetAutomatisation in development and testing - within budget
Automatisation in development and testing - within budget
David Lukac
 
CLI Wizardry - A Friendly Intro To sed/awk/grep
CLI Wizardry - A Friendly Intro To sed/awk/grepCLI Wizardry - A Friendly Intro To sed/awk/grep
CLI Wizardry - A Friendly Intro To sed/awk/grep
All Things Open
 
Serverless in production, an experience report (FullStack 2018)
Serverless in production, an experience report (FullStack 2018)Serverless in production, an experience report (FullStack 2018)
Serverless in production, an experience report (FullStack 2018)
Yan Cui
 
Byte Sized Rust
Byte Sized RustByte Sized Rust
Byte Sized Rust
Steve Hoffman
 
Puppet for dummies - PHPBenelux UG edition
Puppet for dummies - PHPBenelux UG editionPuppet for dummies - PHPBenelux UG edition
Puppet for dummies - PHPBenelux UG editionJoshua Thijssen
 
Aws Lambda in Swift - NSLondon - 3rd December 2020
Aws Lambda in Swift - NSLondon - 3rd December 2020Aws Lambda in Swift - NSLondon - 3rd December 2020
Aws Lambda in Swift - NSLondon - 3rd December 2020
Andrea Scuderi
 
Building a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless frameworkBuilding a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless framework
Luciano Mammino
 
Serverless in Production, an experience report (AWS UG South Wales)
Serverless in Production, an experience report (AWS UG South Wales)Serverless in Production, an experience report (AWS UG South Wales)
Serverless in Production, an experience report (AWS UG South Wales)
Yan Cui
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3
Luciano Mammino
 
Serverless in production, an experience report
Serverless in production, an experience reportServerless in production, an experience report
Serverless in production, an experience report
Yan Cui
 
ESL report
ESL reportESL report
ESL report
Express News
 
Testing API platform with Behat BDD tests
Testing API platform with Behat BDD testsTesting API platform with Behat BDD tests
Testing API platform with Behat BDD tests
Stefan Adolf
 
Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3
kognate
 
Get cfml Into the Box 2018
Get cfml Into the Box 2018Get cfml Into the Box 2018
Get cfml Into the Box 2018
Ortus Solutions, Corp
 

Similar to Serverless, The Middy Way - Workshop (20)

Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​ Middy.js - A powerful Node.js middleware framework for your lambdas​
Middy.js - A powerful Node.js middleware framework for your lambdas​
 
Serverless and React
Serverless and ReactServerless and React
Serverless and React
 
From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
Building Serverless applications with Python
Building Serverless applications with PythonBuilding Serverless applications with Python
Building Serverless applications with Python
 
Automatisation in development and testing - within budget
Automatisation in development and testing - within budgetAutomatisation in development and testing - within budget
Automatisation in development and testing - within budget
 
CLI Wizardry - A Friendly Intro To sed/awk/grep
CLI Wizardry - A Friendly Intro To sed/awk/grepCLI Wizardry - A Friendly Intro To sed/awk/grep
CLI Wizardry - A Friendly Intro To sed/awk/grep
 
Serverless in production, an experience report (FullStack 2018)
Serverless in production, an experience report (FullStack 2018)Serverless in production, an experience report (FullStack 2018)
Serverless in production, an experience report (FullStack 2018)
 
Byte Sized Rust
Byte Sized RustByte Sized Rust
Byte Sized Rust
 
Puppet for dummies - PHPBenelux UG edition
Puppet for dummies - PHPBenelux UG editionPuppet for dummies - PHPBenelux UG edition
Puppet for dummies - PHPBenelux UG edition
 
Aws Lambda in Swift - NSLondon - 3rd December 2020
Aws Lambda in Swift - NSLondon - 3rd December 2020Aws Lambda in Swift - NSLondon - 3rd December 2020
Aws Lambda in Swift - NSLondon - 3rd December 2020
 
ql.io at NodePDX
ql.io at NodePDXql.io at NodePDX
ql.io at NodePDX
 
Building a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless frameworkBuilding a serverless company on AWS lambda and Serverless framework
Building a serverless company on AWS lambda and Serverless framework
 
Serverless in Production, an experience report (AWS UG South Wales)
Serverless in Production, an experience report (AWS UG South Wales)Serverless in Production, an experience report (AWS UG South Wales)
Serverless in Production, an experience report (AWS UG South Wales)
 
How to send gzipped requests with boto3
How to send gzipped requests with boto3How to send gzipped requests with boto3
How to send gzipped requests with boto3
 
Serverless in production, an experience report
Serverless in production, an experience reportServerless in production, an experience report
Serverless in production, an experience report
 
ESL report
ESL reportESL report
ESL report
 
Testing API platform with Behat BDD tests
Testing API platform with Behat BDD testsTesting API platform with Behat BDD tests
Testing API platform with Behat BDD tests
 
Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3Server(less) Swift at SwiftCloudWorkshop 3
Server(less) Swift at SwiftCloudWorkshop 3
 
Get cfml Into the Box 2018
Get cfml Into the Box 2018Get cfml Into the Box 2018
Get cfml Into the Box 2018
 

More from Luciano Mammino

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJS
Luciano Mammino
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Luciano Mammino
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
Luciano Mammino
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!
Luciano Mammino
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLs
Luciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
Luciano Mammino
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
Luciano Mammino
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
Luciano Mammino
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & Airtable
Luciano Mammino
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀
Luciano Mammino
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust Dublin
Luciano Mammino
 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!
Luciano Mammino
 
The senior dev
The senior devThe senior dev
The senior dev
Luciano Mammino
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community Vijayawada
Luciano Mammino
 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)
Luciano Mammino
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made Simple
Luciano Mammino
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti Serverless
Luciano Mammino
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Luciano Mammino
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021
Luciano Mammino
 

More from Luciano Mammino (20)

Did you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJSDid you know JavaScript has iterators? DublinJS
Did you know JavaScript has iterators? DublinJS
 
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
What I learned by solving 50 Advent of Code challenges in Rust - RustNation U...
 
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS MilanoBuilding an invite-only microsite with Next.js & Airtable - ReactJS Milano
Building an invite-only microsite with Next.js & Airtable - ReactJS Milano
 
From Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiperFrom Node.js to Design Patterns - BuildPiper
From Node.js to Design Patterns - BuildPiper
 
Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!Let's build a 0-cost invite-only website with Next.js and Airtable!
Let's build a 0-cost invite-only website with Next.js and Airtable!
 
Everything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLsEverything I know about S3 pre-signed URLs
Everything I know about S3 pre-signed URLs
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
Serverless for High Performance Computing
Serverless for High Performance ComputingServerless for High Performance Computing
Serverless for High Performance Computing
 
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022JavaScript Iteration Protocols - Workshop NodeConf EU 2022
JavaScript Iteration Protocols - Workshop NodeConf EU 2022
 
Building an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & AirtableBuilding an invite-only microsite with Next.js & Airtable
Building an invite-only microsite with Next.js & Airtable
 
Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀Let's take the monolith to the cloud 🚀
Let's take the monolith to the cloud 🚀
 
A look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust DublinA look inside the European Covid Green Certificate - Rust Dublin
A look inside the European Covid Green Certificate - Rust Dublin
 
Monoliths to the cloud!
Monoliths to the cloud!Monoliths to the cloud!
Monoliths to the cloud!
 
The senior dev
The senior devThe senior dev
The senior dev
 
Node.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community VijayawadaNode.js: scalability tips - Azure Dev Community Vijayawada
Node.js: scalability tips - Azure Dev Community Vijayawada
 
A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)A look inside the European Covid Green Certificate (Codemotion 2021)
A look inside the European Covid Green Certificate (Codemotion 2021)
 
AWS Observability Made Simple
AWS Observability Made SimpleAWS Observability Made Simple
AWS Observability Made Simple
 
Semplificare l'observability per progetti Serverless
Semplificare l'observability per progetti ServerlessSemplificare l'observability per progetti Serverless
Semplificare l'observability per progetti Serverless
 
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
Finding a lost song with Node.js and async iterators - NodeConf Remote 2021
 
Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021Finding a lost song with Node.js and async iterators - EnterJS 2021
Finding a lost song with Node.js and async iterators - EnterJS 2021
 

Recently uploaded

Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
OnBoard
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
Product School
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Jeffrey Haguewood
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
Cheryl Hung
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
Thijs Feryn
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
DianaGray10
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
g2nightmarescribd
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
Guy Korland
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
DianaGray10
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Inflectra
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Product School
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Thierry Lestable
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
Safe Software
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
Frank van Harmelen
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
DanBrown980551
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance
 

Recently uploaded (20)

Leading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdfLeading Change strategies and insights for effective change management pdf 1.pdf
Leading Change strategies and insights for effective change management pdf 1.pdf
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdfFIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
FIDO Alliance Osaka Seminar: FIDO Security Aspects.pdf
 
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
Slack (or Teams) Automation for Bonterra Impact Management (fka Social Soluti...
 
Key Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdfKey Trends Shaping the Future of Infrastructure.pdf
Key Trends Shaping the Future of Infrastructure.pdf
 
Accelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish CachingAccelerate your Kubernetes clusters with Varnish Caching
Accelerate your Kubernetes clusters with Varnish Caching
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3UiPath Test Automation using UiPath Test Suite series, part 3
UiPath Test Automation using UiPath Test Suite series, part 3
 
Generating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using SmithyGenerating a custom Ruby SDK for your web service or Rails API using Smithy
Generating a custom Ruby SDK for your web service or Rails API using Smithy
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 
GraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge GraphGraphRAG is All You need? LLM & Knowledge Graph
GraphRAG is All You need? LLM & Knowledge Graph
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
Unsubscribed: Combat Subscription Fatigue With a Membership Mentality by Head...
 
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
Empowering NextGen Mobility via Large Action Model Infrastructure (LAMI): pav...
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*Neuro-symbolic is not enough, we need neuro-*semantic*
Neuro-symbolic is not enough, we need neuro-*semantic*
 
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
LF Energy Webinar: Electrical Grid Modelling and Simulation Through PowSyBl -...
 
FIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdfFIDO Alliance Osaka Seminar: Overview.pdf
FIDO Alliance Osaka Seminar: Overview.pdf
 

Serverless, The Middy Way - Workshop

  • 1. ServerlessServerless The "Middy" wayThe "Middy" way — Workshop    loige.link/middy-way Community Day Dublin October , 1st 2019 Luciano Mammino @loige Wi-Fi: DC_Conference October-2019 1
  • 2. 2
  • 3. Hello, I am Luciano!Hello, I am Luciano! 2
  • 4. Hello, I am Luciano!Hello, I am Luciano! 2
  • 5. Hello, I am Luciano!Hello, I am Luciano! 2
  • 6. Hello, I am Luciano!Hello, I am Luciano! 2
  • 7. Hello, I am Luciano!Hello, I am Luciano! Cloud Architect 2
  • 8. Hello, I am Luciano!Hello, I am Luciano! Cloud Architect Blog: Twitter: GitHub:   loige.co @loige @lmammino 2
  • 9. Hello, I am Luciano!Hello, I am Luciano! Cloud Architect Blog: Twitter: GitHub:   loige.co @loige @lmammino 2
  • 10. Hello, I am Luciano!Hello, I am Luciano! Cloud Architect Blog: Twitter: GitHub:   loige.co @loige @lmammino 2
  • 12. Let's chat on:Let's chat on: tlk.io/middy-waytlk.io/middy-way @loige 4
  • 13. What is serverlessWhat is serverless Compute as functions (FaaS)Compute as functions (FaaS) Event-based modelEvent-based model @loige 5
  • 14. Why serverless is goodWhy serverless is good Focus on business logicFocus on business logic ScalabilityScalability Pay per usage model (compute time * memory)Pay per usage model (compute time * memory) Managed infrastructureManaged infrastructure Forces you to think micro-servicesForces you to think micro-services @loige 6
  • 15. My Serverless experienceMy Serverless experience Open source A semi-automated weekly newsletter ( ) A middleware framework for AWS Lambda ( ) Enterprise Trading, Billing engine, Market data aggregator solutions ( ) Big data pipeline to make network metadata searchable ( ) Organised various workshops around Europe ( ) Fullstack bulletin middy.js.org ESB Vectra.ai Serverlesslab.com @loige 7
  • 16. Let's get this party startedLet's get this party started @loige 8
  • 18. A nice laptopA nice laptop @loige 10
  • 19. An AWS accountAn AWS account    aws.amazon.com/freeaws.amazon.com/free @loige 11
  • 20. Have anHave an admin useradmin user in your AWS accountin your AWS account    loige.link/aws-admin-userloige.link/aws-admin-user @loige 12
  • 21. install the AWS CLIinstall the AWS CLI    aws.amazon.com/cliaws.amazon.com/cli @loige 13
  • 22. configure the AWS CLIconfigure the AWS CLI    loige.link/aws-cli-configloige.link/aws-cli-config @loige 14
  • 23. VerifyVerify aws sts get-caller-identity { "Account": "123456789012", "UserId": "ABCDEFGHIJKLMNOPQRSTU", "Arn": "arn:aws:iam::123456789012:user/super-mario" } @loige 15
  • 24. Install Git and Node.jsInstall Git and Node.js    git-scm.comgit-scm.com nodejs.orgnodejs.org   @loige 16
  • 25. You are ready!You are ready! @loige 17
  • 26. What are we going to build?What are we going to build? @loige 18
  • 27. @loige A realtime dashboard for public transport!A realtime dashboard for public transport! 19
  • 28. loige.link/middy-way-starterloige.link/middy-way-starter Read... the README! Clone the project locally Deploy it to your AWS account Play with the APIs @loige 20
  • 29. loige.link/middy-way-starterloige.link/middy-way-starter Read... the README! Clone the project locally Deploy it to your AWS account Play with the APIs I need staaarz! @loige 20
  • 30. ⏱ 20 mins warm up ♀ ⏱ 20 mins warm up ♀  1. Use the APIs to create a dashboard that contains:1. Use the APIs to create a dashboard that contains: An IrishRail station widget A LUAS stop widget A DublinBus stop widget (there are utility scripts to list all the stops and stations, check the README)   2. Have a look at the code2. Have a look at the code If you find bugs, please send a or report anPR issue @loige 21
  • 31. AWS Lambda & MiddyAWS Lambda & Middy ❤❤ @loige 22
  • 32. The problem with LambdasThe problem with Lambdas @loige 23
  • 33. 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 AWSAnatomy of a Node.js lambda on AWS @loige 24
  • 34. (event, context, callback) => { // decrypt environment variables with KMS // deserialize the content of the event // validate input, authentication, authorization // REAL BUSINESS LOGIC // (process input, generate output) // validate output // serialize response // handle errors } A typical "REAL" Lambda functionA typical "REAL" Lambda function @loige 25
  • 35. (event, context, callback) => { // decrypt environment variables with KMS // deserialize the content of the event // validate input, authentication, authorization // REAL BUSINESS LOGIC // (process input, generate output) // validate output // serialize response // handle errors } A typical "REAL" Lambda functionA typical "REAL" Lambda function @loige 25
  • 36. (event, context, callback) => { // decrypt environment variables with KMS // deserialize the content of the event // validate input, authentication, authorization // REAL BUSINESS LOGIC // (process input, generate output) // validate output // serialize response // handle errors } A typical "REAL" Lambda functionA typical "REAL" Lambda function @loige 25
  • 37. (event, context, callback) => { // decrypt environment variables with KMS // deserialize the content of the event // validate input, authentication, authorization // REAL BUSINESS LOGIC // (process input, generate output) // validate output // serialize response // handle errors } A typical "REAL" Lambda functionA typical "REAL" Lambda function LOTS of BOILERPLATE @loige 25
  • 39. npm install @middy/core Note: using preview (alpha)version 1.0.0 @loige 27
  • 40. npm install @middy/core Note: using preview (alpha)version 1.0.0 Give it moar love @loige 27
  • 41. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = (event, context, callback) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } @loige 28
  • 42. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = (event, context, callback) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 1. define handler @loige 28
  • 43. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = (event, context, callback) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 2. "middify"  the handler @loige 28
  • 44. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = (event, context, callback) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 3. attach middlewares @loige 28
  • 45. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = (event, context, callback) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 4. export "middyfied" handler @loige 28
  • 46. const middy = require('@middy/core') const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser') const validator = require('@middy/validator') const httpErrorHandler = require('@middy/http-error-handler') const processPaymentHandler = (event, context, callback) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return callback(null, { result: 'success', message: 'payment processed correctly'} ) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } @loige 29
  • 47. const middy = require('@middy/core') const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser') const validator = require('@middy/validator') const httpErrorHandler = require('@middy/http-error-handler') const processPaymentHandler = (event, context, callback) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return callback(null, { result: 'success', message: 'payment processed correctly'} ) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } Handler @loige 29
  • 48. const middy = require('@middy/core') const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser') const validator = require('@middy/validator') const httpErrorHandler = require('@middy/http-error-handler') const processPaymentHandler = (event, context, callback) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return callback(null, { result: 'success', message: 'payment processed correctly'} ) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } Attach middlewares @loige 29
  • 49. const middy = require('@middy/core') const urlEncodedBodyParser = require('@middy/http-urlencode-body-parser') const validator = require('@middy/validator') const httpErrorHandler = require('@middy/http-error-handler') const processPaymentHandler = (event, context, callback) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return callback(null, { result: 'success', message: 'payment processed correctly'} ) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } Export enhanced handler @loige 29
  • 52. Why?Why? Simplify code Reusability input parsing input & output validation output serialization error handling ... @loige 30
  • 53. Why?Why? Simplify code Reusability input parsing input & output validation output serialization error handling ... Focus (even) MORE on business logic@loige 30
  • 54. How it worksHow it works @loige 31
  • 57. Execution orderExecution order 1. middleware1 (before) 32@loige
  • 58. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 32@loige
  • 59. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 32@loige
  • 60. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 32@loige
  • 61. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 32@loige
  • 62. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) 32@loige
  • 63. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) 7. middleware1 (after) 32@loige
  • 64. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) 7. middleware1 (after) 32@loige
  • 65. When an error happens...When an error happens... Flow is stopped First middleware implementing `onError` gets control It can choose to handle the error, or delegate it to the next handler If the error is handler a response is returned If the error is not handled the execution fails reporting the unhandled error @loige 33
  • 66. Writing a middlewareWriting a middleware const myMiddleware = (config) => { // might set default options in config return ({ before: (handler, next) => { // might read options from `config` }, after: (handler, next) => { // might read options from `config` }, onError: (handler, next) => { // might read options from `config` } }) } module.exports = myMiddleware @loige 34
  • 67. Inline middlewaresInline middlewares const middy = require('@middy/core') const handler = middy((event, context, callback) => { // do stuff }) handler.before((handler, next) => { // do something in the before phase next() }) handler.after((handler, next) => { // do something in the after phase next() }) handler.onError((handler, next) => { // do something in the on error phase next() }) module.exports = { handler } @loige 35
  • 68. It supports async handlers!It supports async handlers! const middy = require('@middy/core') const handler = middy( async (event, context) => { // do stuff return { some: 'response' } } ) module.exports = { handler } @loige 36
  • 69. Exercise 0Exercise 0: let's middify!: let's middify! In the next exercises we will need the full power of middy, so to get started let's just "middify" all our handlers — Note: handlers are defined in "src/handlers", and they get used in "src/handler.js". You can either middify every single handler file or middify them when used in src/handler.js. In the first case, make sure you middify the actual handler function and not the "handler factory".   ( )a solution @loige 37
  • 70. Exercise 1Exercise 1: body parsing: body parsing We are manually deserializing the JSON input in our APIs. We can simplify the code a bit by using the middleware. —   Install @middy/http-json-body-parser and remove all the instances of JSON.parse() in our handlers.   ( ) http-json-body-parser a solution @loige 38
  • 71. What happens when one of our handlers crashes? We are actually not even dealing with errors right now... by using the  middleware we will be able to handle all HTTP errors and return codes consistently. —   Install @middy/http-error-handler and apply that to all our handlers.   ( ) http-error-handler a solution Exercise 2Exercise 2: what if we fail?: what if we fail? @loige 39
  • 72. We want to make sure that data is validated before being written to the database. We can use the middleware for this task! — Install @middy/validator and apply that to all our POST API handlers. You can use  to define your schemas or, if you are struggling, you can find some schemas ready-made for you  :)   Note: The validator should be added after the json-body-parser, so you can validate individual fields of the input data.   ( ) validator jsonschema.net here a solution Exercise 3Exercise 3: validate!: validate! @loige 40
  • 73. We have our dashboards fully working, but consuming them in JSON is definitely not the friendliest experience! It would be much better to do in a properly rendered HTML so that we could easily visualize them on our mobile device! — You can implement this in (at least) 2 ways : Using the middleware and building a frontend somewhere like or Using the middleware and implementing a specific rule for accept "text/html"   ( - ) http-cors codesandbox codepen http-content-negotiation a CORS solution a CodeSandbox React UI Exercise 4Exercise 4: mobile rendering: mobile rendering @loige 41
  • 74. Did you notice that our APIs are fully open? Knowing the endpoint and the id, anyone can basically change or delete the dashboards! That's unacceptable! — Find a way to secure the APIs. One easy way could be to create a secret random token when a dashboard is created the first time. Then you can create a custom middleware that checks the secret every time someone is trying to modify or delete that dashboard!   Note: if you feel fancy you can use JWT tokens, in such case you could take inspiration from the middleware!jwt-auth Exercise 5Exercise 5: better safe than sorry: better safe than sorry @loige 42
  • 75. Sometimes our APIs are very slow. They take literally seconds to answer. This is because of a common serverless issue known as " ". If you are running for your train every morning, this is unacceptable! We should fix this... —   Use the  middleware to mitigate the cold start issue   Note: make sure to also setup the proper event for every API.  cold start problem warmup schedule 2 @loige Exercise 6Exercise 6: stop the cold!: stop the cold! 43
  • 76. Some of your Java friends would love to use these APIs to build a shiny SWING UI... The problem is that they don't really like JSON and they would rather have a good old XML-based API. You might think that this is actually their problem, but also, you don't want to lose your friends... —   Use the  middleware to provide responses in XML for accept "application/xml".   Note: You could use a library like  to automate the conversion of JavaScript objects to XML. http-content-negotiation json2xml @loige Exercise 7Exercise 7: legacy friendship: legacy friendship 44
  • 77. In summaryIn summary Serverless is cool, it helps you to build apps quickly and with a greater focus on business logic, rather than on infrastructure! Middy helps you to keep focusing on your business logic first You can add extra behaviours with very minimal changes to your core logic by introducing dedicated middlewares You can easily share common functionality through middlewares 45
  • 78. If you like MiddyIf you like Middy Use itUse it Give feedbackGive feedback Contribute (I am looking for co-maintainers)Contribute (I am looking for co-maintainers) Version 1.0 (stable) coming soonVersion 1.0 (stable) coming soon 46
  • 80. CreditsCredits Cover Image by  from   A special thank you to all the amazing Middy users and !   Thanks to for reviewing these slides and to  for finding lots of bugs! TotumRevolutum Pixabay contributors @StefanoAbalsamo @organicdelight @loige 48