Deploy a Koa.js server on an AWS Lambda function using Serverless
Deploy Koa.js server - Edition #30
Hey, I'm Marco and welcome to my newsletter!
As a software engineer, I created this newsletter to share my first-hand knowledge of the development world. Each topic we will explore will provide valuable insights, with the goal of inspiring and helping all of you on your journey.
In this episode, I show you how to deploy your Koa.js application in a Lambda function with AWS.
You can download all the code shown directly from my Github repository: https://github.com/marcomoauro/lambda-node-backend-template
👋 Introduction
In the previous episode, we saw how to deploy a Lambda function using Serverless, with the trigger calling a function in a JavaScript module.
(serverless.yml)
...
functions:
hello:
handler: handler.hello
...
(handler.js)
...
export const hello = async (event) => {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Hello from Implementing!'
})
};
};
...
With the Serverless framework it is also possible to deploy applications made with technologies such as Express, Koa.js and many others, with minimal overhead.
The result will be a single Lambda function will be deployed that exposes the application and delegates routing management to it, if configured appropriately.
In this way, development can continue as usual with minimal changes to the developer experience, making it easy to introduce the framework even to teams unfamiliar with Serverless technology.
👨💻 Let's implement together
You can download all the code shown directly from my Github repository: https://github.com/marcomoauro/lambda-node-backend-template
The structure of the application is similar to the one I use in all my projects that I then deploy on Heroku, a detailed explanation can be found here:
Create Koa.js app
Similar to the template I always use, the only difference is that the app created with the Koa library is not used to create an HTTP server.
Middleware and routes are registered in the app and then exported:
import cors from '@koa/cors';
import Koa from 'koa';
import json from 'koa-better-json';
import {koaBody} from 'koa-body';
import {APIError404, APIError405, APIError415, apiErrorManager} from './errors.js';
import log from './log.js';
import {
initAsyncStorage,
logIncomingCall,
routeSummaryLog
} from './middlewares.js';
import router from './router.js';
process.on('uncaughtException', (e) => log.error('uncaughtException', e));
process.on('unhandledRejection', (e) => log.error('unhandledRejection', e));
const app = new Koa();
const body_limits = {
formLimit: '64mb',
jsonLimit: '64mb',
formidable: {maxFileSize: '64mb', multiples: true},
multipart: true,
};
app.use(cors({exposeHeaders: ['x-version']}));
app.use(koaBody(body_limits));
app.use(json());
app.use(initAsyncStorage);
app.use(routeSummaryLog);
app.use(logIncomingCall);
app.use(async (ctx, next) => {
try {
ctx.set('x-version', process.env.npm_package_version);
await next();
if (!ctx.body) {
// if body is not defined at this moment, it means that no route matched the request, so a 404 error is fired.
throw new APIError404();
}
} catch (error) {
apiErrorManager(ctx, error); // error handler
}
});
app.use(router.routes());
app.use(
router.allowedMethods({
throw: true,
notImplemented: () => new APIError415(),
methodNotAllowed: () => new APIError405(),
}),
);
export default app;
Expose app with serverless-http
To expose the app we can use the serverless-http, this library allows you to “wrap” your API for serverless use.
We can install it by executing:
npm i serverless-http
We create a lambda.js module like this one:
import slsHttp from 'serverless-http'
import app from './src/app.js'
export const handler = slsHttp(app)
and we will configure the handler in the serverless.yml configuration file:
(serverless.yml)
...
functions:
app:
handler: lambda.handler
events:
- httpApi:
path: /{proxy+}
method: ANY
...
Environmental variables management
Keep reading with a 7-day free trial
Subscribe to Implementing to keep reading this post and get 7 days of free access to the full post archives.