In the era of cloud computing, infrastructure as code (IaC) is the way to go for managing your resources. With the rise of serverless, which often leads to finer granular deployments, it’s even more important to have one source of truth for your whole infrastructure.
Sadly, though, things aren’t as straightforward as they seem. IaC tools like CloudFormation (CFN) have grown over the years. CFN includes most resources AWS has to offer, and it uses YAML as a file format to define those resources. However, if you want to define your serverless systems with plain CFN, you run into problems.
Every Lambda function needs permissions to access other AWS services, and every AWS service that wants to access a Lambda function also needs permissions to do so. A dozen Lambda functions multiplied by all those permissions can get quite cumbersome. You also need to link up your events to connect them with API gateways and databases.
All this has led to the creation of tools that automate the ceremony of explicitly provisioning supporting services. One of them is the Architect framework (ARC), a project of the OpenJS foundation. ARC is an IaC framework that lets developers define their serverless infrastructure in a concise way. It’s used as the IaC framework of choice by Begin, a service built on top of AWS that tries to ease the building and deployment of serverless apps and APIs.
AWS Resources as ARC Pragmas
ARC lets you define your infrastructure in .arc files that have a very simple flat syntax. A serverless REST API for books could look like this:
@app
books-api
@http
post /books # create
get /books # list
get /books/:bookID # read
patch /books/:bookID # update
delete /books/:bookID # delete
The @app
pragma defines the name of the app, and the @http
pragma lets you define serverless functions triggered by HTTP requests.
ARC favors “convention over configuration,” so it will assume the actual code for the serverless function is in a predefined place, with the default runtime being Node.js. In our example above, the file for our list function should be located in src/http/get-books/index.js
. If you run ARC’s init
command in a directory with an app.arc
file, it will automatically generate those JavaScript files for you in the right places.
If we want to save files into an S3 bucket, we can use the @static pragma. To run a Lambda function on a schedule instead of an HTTP request, we can use @scheduled. We can even drop our files onto CloudFront by using @cdn; there’s no need to define API Gateway and Lambda resources independently.
Local Sandboxing
Another nice feature that’s also missing from CFN is local sandboxing. This allows you to run Lambda functions on a development machine without having to deploy it to AWS first. The ability to run and debug locally drastically increases development velocity and helps you find problems right when a new feature is created.
If you run the following code inside an ARC project, it will start a development server on a free port for you:
$ arc sandbox
Example Application
Let’s build a sample application with ARC, a small website that talks to a serverless API.
Prerequisites
To follow this tutorial, you’ll need NPM installed. It’s installed automatically when you install Node.js. You’ll also need an AWS account and an AWS CLI installation for the deployment at the end.
Install the CLI Tool
To run the commands, you’ll first need to install the ARC CLI tool, which you can do via NPM.
$ npm i -g @architect/architect
Running the Code Generator
ARC can generate code, but it needs an arc-file to do so. Create a new project directory called example
with an app.arc
file that contains the following code:
@app
example
@static
@http
get /api
If you run ARC’s init
command, it will generate the required code for you in the project directory:
$ arc init
After running the init command you should have two new directories:
example/public
, with a generated HTML and JS file inside for the website we will display.example/src/http/get-api
, with a JS file for the Lambda function that handles our API requests.
Running the Sandbox Environment
With these files, you can already run the sandbox environment and see something, so run the following command:
$ arc sandbox
With the development server running, you can visit two URLs with your browser.
The first URL is http://localhost:3333, which returns with the website that was generated by ARC inside the example/public
directory as the response. If you look inside the browser console, you can see that ARC also generated JavaScript for you that is executed when you visit the site.
The second URL is http://localhost:3333/api, which is the Lambda function that responds here, although the default response is also HTML. It explains where to find the code for that API endpoint.
Implementing the API
We can implement a simple date API by replacing the Lambda function code inside example/src/http/get-api/index.js
with this code:
xports.handler = async () => ({
statusCode: 200,
body: JSON.stringify({
date: Date(),
}),
});
Now, your API responds with a date string inside a JSON object. We can see the result when we visit http://localhost:3333/api again with a browser.
Implementing the Client
To get the client connected with our serverless API, we have to replace the contents of example/public/index.js
with this implementation:
fetch("/api")
.then((response) => response.json())
.then(({ date }) => alert(date));
This will send a request to the /api endpoint, convert the response to a JavaScript object, and show a popup with the date string.
Deploying to AWS
The finishing touch is to deploy everything to your AWS account. This will generate a CFN template to deploy the Lambda function and configure it with API Gateway and IAM policies. The command will also upload the static assets from the example/public
directory to an S3 bucket.
To deploy, you’ll just need to run the following command:
$ arc deploy
This command takes some time to run, and once it is finished, it will supply you with a new URL pointing to the deployment on the AWS cloud.
Running the deploy
command without any flags will deploy to a staging environment. If you want to deploy to production, you’ll have to use the production
flag.
Should You Use the Architect Framework?
The pain of fine granular provisioning of infrastructure is a well-known problem, so it is no surprise that there are many frameworks that try to solve it.
AWS has also created its own frameworks: AWS SAM tries to extend CFN with serverless resources, so people who know CFN feel at home. AWS CDK tries to facilitate IaC by deviating from the known YAML config files and using fully-fledged programming languages like Java, Python, or TypeScript.
ARC tries to go a new way—small, fast, concise—bringing the “convention over configuration” wonders known from Ruby on Rails to the serverless world. It has its own configuration language, but this language is really minimal and easy for newcomers to grasp. The ARC CLI tool comes with code generators and local sandbox environments and is blazingly fast. Low-code and well-integrated local development out-of-the-box are features that other frameworks lack.
It’s also comforting to know that it’s a project of the OpenJS foundation and that it’s used in production by the Begin service. Both these facts make ARC a serious contender in the serverless framework world.