SlideShare a Scribd company logo
Middy.js
A powerful Node.js middleware framework for your lambdas 
Luciano Mammino ( )@loige
loige.link/middy-gcs29/01/2020, Dublin 1
2
Hello, I am Luciano!Hello, I am Luciano!
2
Hello, I am Luciano!Hello, I am Luciano!
Fullstack Dev & Cloud Architect
2
Hello, I am Luciano!Hello, I am Luciano!
Fullstack Dev & Cloud Architect
Blog:
Twitter:
GitHub:  
loige.co
@loige
@lmammino
2
Hello, I am Luciano!Hello, I am Luciano!
Fullstack Dev & Cloud Architect
Blog:
Twitter:
GitHub:  
loige.co
@loige
@lmammino
2
Ask questions here:
loige.link/middy-gcsloige.link/middy-gcs
loige.link/middy-gcs-qa@loige 3
What is serverlessWhat is serverless
Compute as functions (FaaS)Compute as functions (FaaS)
Event-based modelEvent-based model
Managed resourcesManaged resources
@loige loige.link/middy-gcs-qa4
Why serverless is goodWhy serverless is good
Focus on business logicFocus on business logic
ScalabilityScalability
Pay-per-use model (compute time * memory)Pay-per-use model (compute time * memory)
Forces you to think micro-servicesForces you to think micro-services
@loige loige.link/middy-gcs-qa5
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 loige.link/middy-gcs-qa6
♀ ♀ DISCLAIMERDISCLAIMER
 
Serverless is more than just FaaSServerless is more than just FaaS
 
... but here we will focus mostly on AWS Lamda... but here we will focus mostly on AWS Lamda
@loige loige.link/middy-gcs-qa7
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa8
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa
code
8
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa
code
8
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa
code
⚡
event
8
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa
code
⚡
event
8
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa
code
⚡
event
=
8
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa
code
⚡
event profit
=
8
Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)!
@loige loige.link/middy-gcs-qa
code
⚡
event profit
=
* real life coding with Lambda is a little bit more complicated™ than this...
8
exports.myLambda = async function (
event,
context
) {
// get input from event and context
// return output or throw an error
}
Anatomy of a Node.js lambda on AWSAnatomy of a Node.js lambda on AWS
@loige loige.link/middy-gcs-qa9
exports.myLambda = async function (event, context) {
const name = event.queryStringParameters.name
const message = `Hello ${name || 'World'}!`
return ({
statusCode: 200,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message })
})
}
Hello World!Hello World!
@loige loige.link/middy-gcs-qa10
exports.MyLambda = async function (event, context) {
// 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
}
Real WorldReal World   vsvs  Hello WorldHello World
@loige loige.link/middy-gcs-qa11
exports.MyLambda = async function (event, context) {
// 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
}
Real WorldReal World   vsvs  Hello WorldHello World
@loige loige.link/middy-gcs-qa11
exports.MyLambda = async function (event, context) {
// 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
}
Real WorldReal World   vsvs  Hello WorldHello World
@loige loige.link/middy-gcs-qa11
exports.MyLambda = async function (event, context) {
// 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
}
Real WorldReal World   vsvs  Hello WorldHello World
LOTS of BOILERPLATE
@loige loige.link/middy-gcs-qa11
♀ ♀ 
In a real project with many lambdas,In a real project with many lambdas,
we might end up with a lot of code duplication!we might end up with a lot of code duplication!
@loige loige.link/middy-gcs-qa12
Can we avoid a bit of clutter by separating "Can we avoid a bit of clutter by separating "purepure
business logicbusiness logic" from the "" from the "boilerplateboilerplate"?"?
@loige loige.link/middy-gcs-qa13
A solution...A solution...
@loige loige.link/middy-gcs-qa14
npm install @middy/core
Note: using  (beta)version 1.0.0
@loige loige.link/middy-gcs-qa15
npm install @middy/core
Note: using  (beta)version 1.0.0
Give it moar love
@loige loige.link/middy-gcs-qa15
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
@loige loige.link/middy-gcs-qa16
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
1. define handler
@loige loige.link/middy-gcs-qa16
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
2. "middify"  the handler
@loige loige.link/middy-gcs-qa16
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
3. attach middlewares
@loige loige.link/middy-gcs-qa16
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler } 4. export "middyfied" handler
@loige loige.link/middy-gcs-qa16
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
@loige loige.link/middy-gcs-qa17
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
Business logic
@loige loige.link/middy-gcs-qa17
UsageUsage
const middy = require('@middy/core')
const { middleware1, middleware2, middleware3 } = require('some-middlewares')
const originalHandler = async (event, context) => {
/* your business logic */
}
const handler = middy(originalHandler)
handler
.use(middleware1())
.use(middleware2())
.use(middleware3())
module.exports = { handler }
Business logic
Boilerplate
@loige loige.link/middy-gcs-qa17
Middy comes with a built-in collectionMiddy comes with a built-in collection
of useful middlewaresof useful middlewares
Some examples:
Cache
Database manager
HTTP error handler
HTTP content negotiation
HTTP CORS
HTTP JSON body parser
HTTP Multipart body parser
HTTP Security headers
Secrets manager
SSM
Validator
Warmup
@loige loige.link/middy-gcs-qa18
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 = async (event, context) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return ({
statusCode: 200,
body: 'payment processed correctly'
})
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler }
19
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 = async (event, context) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return ({
statusCode: 200,
body: 'payment processed correctly'
})
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler }
Dependencies
19
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 = async (event, context) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return ({
statusCode: 200,
body: 'payment processed correctly'
})
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler }
Handler
(business logic)
19
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 = async (event, context) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return ({
statusCode: 200,
body: 'payment processed correctly'
})
}
const inputSchema = {
// define validation schema here ...
}
const handler = middy(processPaymentHandler)
.use(urlEncodedBodyParser())
.use(validator(inputSchema))
.use(httpErrorHandler())
module.exports = { handler }
Define the input schema
(uses )JSON-schema
19
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 = async (event, context) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return ({
statusCode: 200,
body: '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
19
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 = async (event, context) => {
const {
creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount
} = event.body
// do stuff with this data ...
return ({
statusCode: 200,
body: '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 19
Why?Why?
@loige loige.link/middy-gcs-qa20
Why?Why?
Simplify code
@loige loige.link/middy-gcs-qa20
Why?Why?
Simplify code
Reusability
input parsing
input & output validation
output serialization
error handling...
@loige loige.link/middy-gcs-qa20
Why?Why?
Simplify code
Reusability
input parsing
input & output validation
output serialization
error handling...
Focus (even) MORE on business logic
Testability
@loige loige.link/middy-gcs-qa20
How it worksHow it works
@loige loige.link/middy-gcs-qa21
Execution orderExecution order
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
6. middleware2 (after)
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
6. middleware2 (after)
7. middleware1 (after)
@loige 22loige.link/middy-gcs-qa
Execution orderExecution order
1. middleware1 (before)
2. middleware2 (before)
3. middleware3 (before)
4. handler
5. middleware3 (after)
6. middleware2 (after)
7. middleware1 (after)
@loige 22loige.link/middy-gcs-qa
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 loige.link/middy-gcs-qa23
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 loige.link/middy-gcs-qa24
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
@loige loige.link/middy-gcs-qa25
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
@loige loige.link/middy-gcs-qa26
If you like MiddyIf you like Middy
Use itUse it
Give feedback:Give 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
github.com/middyjs/middy/issuesgithub.com/middyjs/middy/issues
@loige loige.link/middy-gcs-qa27
Your turn...Your turn...
@loige loige.link/middy-gcs-qa28
THANKS!THANKS!
A special thank you to all the amazing Middy users
and !contributors
@loige
loige.link/middy-gcsloige.link/middy-gcs 29

More Related Content

PDF
Serverless, The Middy Way - Workshop
PDF
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
PDF
How to send gzipped requests with boto3
PPTX
Avoiding Callback Hell with Async.js
PDF
Callbacks, promises, generators - asynchronous javascript
PDF
Javascript Promises/Q Library
PDF
Asynchronous programming done right - Node.js
PDF
Callbacks and control flow in Node js
Serverless, The Middy Way - Workshop
Introducing Middy, Node.js middleware engine for AWS Lambda (FrontConf Munich...
How to send gzipped requests with boto3
Avoiding Callback Hell with Async.js
Callbacks, promises, generators - asynchronous javascript
Javascript Promises/Q Library
Asynchronous programming done right - Node.js
Callbacks and control flow in Node js

What's hot (20)

PDF
JavaOne 2013: Java 8 - The Good Parts
PPTX
Avoiding callback hell in Node js using promises
PDF
JavaScript Promises
PDF
$q and Promises in AngularJS
PDF
Promise pattern
PDF
Asynchronous Programming FTW! 2 (with AnyEvent)
PDF
Asynchronous programming patterns in Perl
PPTX
Promises, Promises
PPTX
Perl: Coro asynchronous
PDF
Mirage For Beginners
PDF
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
PPTX
Building Progressive Web Apps for Windows devices
PDF
Diving into HHVM Extensions (PHPNW Conference 2015)
PDF
Puppet and the HashiStack
PDF
CLS & asyncListener: asynchronous observability for Node.js
PDF
Bootstrapping multidc observability stack
PDF
Why Redux-Observable?
PDF
Finatra v2
PDF
Avoiding callback hell with promises
PDF
Any event intro
JavaOne 2013: Java 8 - The Good Parts
Avoiding callback hell in Node js using promises
JavaScript Promises
$q and Promises in AngularJS
Promise pattern
Asynchronous Programming FTW! 2 (with AnyEvent)
Asynchronous programming patterns in Perl
Promises, Promises
Perl: Coro asynchronous
Mirage For Beginners
Node.js: Continuation-Local-Storage and the Magic of AsyncListener
Building Progressive Web Apps for Windows devices
Diving into HHVM Extensions (PHPNW Conference 2015)
Puppet and the HashiStack
CLS & asyncListener: asynchronous observability for Node.js
Bootstrapping multidc observability stack
Why Redux-Observable?
Finatra v2
Avoiding callback hell with promises
Any event intro
Ad

Similar to Middy.js - A powerful Node.js middleware framework for your lambdas​ (20)

PDF
OutSystsems User Group Netherlands September 2024.pdf
PDF
Building a serverless company on AWS lambda and Serverless framework
PDF
Decoupled APIs through Microservices
PDF
Microservices and the Art of Taming the Dependency Hell Monster
PDF
Communication between (micro-)services - Bernd Rücker - Codemotion Amsterdam ...
PDF
Learn backend java script
PDF
Plataforma distribuída de Microserviços ou, como a Olist funciona
PPTX
Event mesh APIDays melbourne September 2019
PPTX
Introduction to Node js
PDF
Full Stack Serverless 1st Edition Nader Dabit
PDF
Decoupled APIs through microservices
PDF
Design Microservice Architectures the Right Way
PPTX
APIs, STOP Polling, lets go Streaming
PDF
Olist Architecture v2.0
PDF
Full Stack Serverless 1st Edition Nader Dabit
DOCX
RabbitMQ in Microservice Architecture.docx
PDF
Microservices - opportunities, dilemmas and problems
KEY
Event Driven Architecture
PDF
SAI - Serverless Integration Architectures - 09/2019
PPTX
Microservices with .Net - NDC Sydney, 2016
OutSystsems User Group Netherlands September 2024.pdf
Building a serverless company on AWS lambda and Serverless framework
Decoupled APIs through Microservices
Microservices and the Art of Taming the Dependency Hell Monster
Communication between (micro-)services - Bernd Rücker - Codemotion Amsterdam ...
Learn backend java script
Plataforma distribuída de Microserviços ou, como a Olist funciona
Event mesh APIDays melbourne September 2019
Introduction to Node js
Full Stack Serverless 1st Edition Nader Dabit
Decoupled APIs through microservices
Design Microservice Architectures the Right Way
APIs, STOP Polling, lets go Streaming
Olist Architecture v2.0
Full Stack Serverless 1st Edition Nader Dabit
RabbitMQ in Microservice Architecture.docx
Microservices - opportunities, dilemmas and problems
Event Driven Architecture
SAI - Serverless Integration Architectures - 09/2019
Microservices with .Net - NDC Sydney, 2016
Ad

More from Luciano Mammino (20)

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

Recently uploaded (20)

PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Empathic Computing: Creating Shared Understanding
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Machine learning based COVID-19 study performance prediction
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Network Security Unit 5.pdf for BCA BBA.
“AI and Expert System Decision Support & Business Intelligence Systems”
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Empathic Computing: Creating Shared Understanding
MYSQL Presentation for SQL database connectivity
Spectral efficient network and resource selection model in 5G networks
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Reach Out and Touch Someone: Haptics and Empathic Computing
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Per capita expenditure prediction using model stacking based on satellite ima...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Machine learning based COVID-19 study performance prediction
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
20250228 LYD VKU AI Blended-Learning.pptx
Dropbox Q2 2025 Financial Results & Investor Presentation
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Digital-Transformation-Roadmap-for-Companies.pptx
Building Integrated photovoltaic BIPV_UPV.pdf
The AUB Centre for AI in Media Proposal.docx
Network Security Unit 5.pdf for BCA BBA.

Middy.js - A powerful Node.js middleware framework for your lambdas​

  • 1. Middy.js A powerful Node.js middleware framework for your lambdas  Luciano Mammino ( )@loige loige.link/middy-gcs29/01/2020, Dublin 1
  • 2. 2
  • 3. Hello, I am Luciano!Hello, I am Luciano! 2
  • 4. Hello, I am Luciano!Hello, I am Luciano! Fullstack Dev & Cloud Architect 2
  • 5. Hello, I am Luciano!Hello, I am Luciano! Fullstack Dev & Cloud Architect Blog: Twitter: GitHub:   loige.co @loige @lmammino 2
  • 6. Hello, I am Luciano!Hello, I am Luciano! Fullstack Dev & Cloud Architect Blog: Twitter: GitHub:   loige.co @loige @lmammino 2
  • 8. What is serverlessWhat is serverless Compute as functions (FaaS)Compute as functions (FaaS) Event-based modelEvent-based model Managed resourcesManaged resources @loige loige.link/middy-gcs-qa4
  • 9. Why serverless is goodWhy serverless is good Focus on business logicFocus on business logic ScalabilityScalability Pay-per-use model (compute time * memory)Pay-per-use model (compute time * memory) Forces you to think micro-servicesForces you to think micro-services @loige loige.link/middy-gcs-qa5
  • 10. 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 loige.link/middy-gcs-qa6
  • 11. ♀ ♀ DISCLAIMERDISCLAIMER   Serverless is more than just FaaSServerless is more than just FaaS   ... but here we will focus mostly on AWS Lamda... but here we will focus mostly on AWS Lamda @loige loige.link/middy-gcs-qa7
  • 12. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa8
  • 13. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa code 8
  • 14. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa code 8
  • 15. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa code ⚡ event 8
  • 16. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa code ⚡ event 8
  • 17. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa code ⚡ event = 8
  • 18. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa code ⚡ event profit = 8
  • 19. Quickest intro to Lambda (ever)!Quickest intro to Lambda (ever)! @loige loige.link/middy-gcs-qa code ⚡ event profit = * real life coding with Lambda is a little bit more complicated™ than this... 8
  • 20. exports.myLambda = async function ( event, context ) { // get input from event and context // return output or throw an error } Anatomy of a Node.js lambda on AWSAnatomy of a Node.js lambda on AWS @loige loige.link/middy-gcs-qa9
  • 21. exports.myLambda = async function (event, context) { const name = event.queryStringParameters.name const message = `Hello ${name || 'World'}!` return ({ statusCode: 200, headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ message }) }) } Hello World!Hello World! @loige loige.link/middy-gcs-qa10
  • 22. exports.MyLambda = async function (event, context) { // 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 } Real WorldReal World   vsvs  Hello WorldHello World @loige loige.link/middy-gcs-qa11
  • 23. exports.MyLambda = async function (event, context) { // 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 } Real WorldReal World   vsvs  Hello WorldHello World @loige loige.link/middy-gcs-qa11
  • 24. exports.MyLambda = async function (event, context) { // 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 } Real WorldReal World   vsvs  Hello WorldHello World @loige loige.link/middy-gcs-qa11
  • 25. exports.MyLambda = async function (event, context) { // 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 } Real WorldReal World   vsvs  Hello WorldHello World LOTS of BOILERPLATE @loige loige.link/middy-gcs-qa11
  • 26. ♀ ♀  In a real project with many lambdas,In a real project with many lambdas, we might end up with a lot of code duplication!we might end up with a lot of code duplication! @loige loige.link/middy-gcs-qa12
  • 27. Can we avoid a bit of clutter by separating "Can we avoid a bit of clutter by separating "purepure business logicbusiness logic" from the "" from the "boilerplateboilerplate"?"? @loige loige.link/middy-gcs-qa13
  • 28. A solution...A solution... @loige loige.link/middy-gcs-qa14
  • 29. npm install @middy/core Note: using  (beta)version 1.0.0 @loige loige.link/middy-gcs-qa15
  • 30. npm install @middy/core Note: using  (beta)version 1.0.0 Give it moar love @loige loige.link/middy-gcs-qa15
  • 31. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } @loige loige.link/middy-gcs-qa16
  • 32. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 1. define handler @loige loige.link/middy-gcs-qa16
  • 33. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 2. "middify"  the handler @loige loige.link/middy-gcs-qa16
  • 34. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 3. attach middlewares @loige loige.link/middy-gcs-qa16
  • 35. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } 4. export "middyfied" handler @loige loige.link/middy-gcs-qa16
  • 36. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } @loige loige.link/middy-gcs-qa17
  • 37. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } Business logic @loige loige.link/middy-gcs-qa17
  • 38. UsageUsage const middy = require('@middy/core') const { middleware1, middleware2, middleware3 } = require('some-middlewares') const originalHandler = async (event, context) => { /* your business logic */ } const handler = middy(originalHandler) handler .use(middleware1()) .use(middleware2()) .use(middleware3()) module.exports = { handler } Business logic Boilerplate @loige loige.link/middy-gcs-qa17
  • 39. Middy comes with a built-in collectionMiddy comes with a built-in collection of useful middlewaresof useful middlewares Some examples: Cache Database manager HTTP error handler HTTP content negotiation HTTP CORS HTTP JSON body parser HTTP Multipart body parser HTTP Security headers Secrets manager SSM Validator Warmup @loige loige.link/middy-gcs-qa18
  • 40. 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 = async (event, context) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return ({ statusCode: 200, body: 'payment processed correctly' }) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } 19
  • 41. 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 = async (event, context) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return ({ statusCode: 200, body: 'payment processed correctly' }) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } Dependencies 19
  • 42. 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 = async (event, context) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return ({ statusCode: 200, body: 'payment processed correctly' }) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } Handler (business logic) 19
  • 43. 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 = async (event, context) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return ({ statusCode: 200, body: 'payment processed correctly' }) } const inputSchema = { // define validation schema here ... } const handler = middy(processPaymentHandler) .use(urlEncodedBodyParser()) .use(validator(inputSchema)) .use(httpErrorHandler()) module.exports = { handler } Define the input schema (uses )JSON-schema 19
  • 44. 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 = async (event, context) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return ({ statusCode: 200, body: '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 19
  • 45. 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 = async (event, context) => { const { creditCardNumber, expiryMonth, expiryYear, cvc, nameOnCard, amount } = event.body // do stuff with this data ... return ({ statusCode: 200, body: '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 19
  • 48. Why?Why? Simplify code Reusability input parsing input & output validation output serialization error handling... @loige loige.link/middy-gcs-qa20
  • 49. Why?Why? Simplify code Reusability input parsing input & output validation output serialization error handling... Focus (even) MORE on business logic Testability @loige loige.link/middy-gcs-qa20
  • 50. How it worksHow it works @loige loige.link/middy-gcs-qa21
  • 51. Execution orderExecution order @loige 22loige.link/middy-gcs-qa
  • 52. Execution orderExecution order @loige 22loige.link/middy-gcs-qa
  • 53. Execution orderExecution order 1. middleware1 (before) @loige 22loige.link/middy-gcs-qa
  • 54. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) @loige 22loige.link/middy-gcs-qa
  • 55. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) @loige 22loige.link/middy-gcs-qa
  • 56. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler @loige 22loige.link/middy-gcs-qa
  • 57. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) @loige 22loige.link/middy-gcs-qa
  • 58. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) @loige 22loige.link/middy-gcs-qa
  • 59. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) 7. middleware1 (after) @loige 22loige.link/middy-gcs-qa
  • 60. Execution orderExecution order 1. middleware1 (before) 2. middleware2 (before) 3. middleware3 (before) 4. handler 5. middleware3 (after) 6. middleware2 (after) 7. middleware1 (after) @loige 22loige.link/middy-gcs-qa
  • 61. 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 loige.link/middy-gcs-qa23
  • 62. 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 loige.link/middy-gcs-qa24
  • 63. 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 @loige loige.link/middy-gcs-qa25
  • 64. 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 @loige loige.link/middy-gcs-qa26
  • 65. If you like MiddyIf you like Middy Use itUse it Give feedback:Give 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 github.com/middyjs/middy/issuesgithub.com/middyjs/middy/issues @loige loige.link/middy-gcs-qa27
  • 66. Your turn...Your turn... @loige loige.link/middy-gcs-qa28
  • 67. THANKS!THANKS! A special thank you to all the amazing Middy users and !contributors @loige loige.link/middy-gcsloige.link/middy-gcs 29