Bringing spatial interfaces to Zeit’s Now v2 platform

Dennis Bauszus
5 min readMar 7, 2020

I have previously written about GEOLYTIX’ work to make spatial interfaces serverless with Zeit’s Now platform. Soon after I published that article, Zeit introduced the second coming of their Now cloud platform for static sites and Serverless Functions. Everything changed and we had to go with the flow.

Now Again with Serverless Function

Being able to deploy functions written for the Node.js runtime allowed us to break up the XYZ web server into individual handler for each endpoint. Once build, each handler will be a Serverless Function in an immutable deployment hosted as a Zeit Project. Zeit uses regional AWS cloud services as origin for Serverless Functions as well as the Google Cloud Platform to provide edge caching for static content in the Zeit CDN.

Benefits

Abstracting away cloud providers improves resilience with a minimum off fuss by not having to deal with different cloud consoles. Having no servers to maintain while further reducing NoOps costs makes the Zeit Now platform the most reasonable choice for GEOLYTIX’ cloud services. As of March ’20, Zeit even offer a free tier for hobbyists.

Reducing cost is at the heart of going serverless. Whether it is the price of Metal, DevOps or redundant uptime.

From serverful to serverless function handler

The legacy serverful behavior was to deploy a code repository to Zeit and let the Node.js runtime build and subsequently run a Fastify web server. Serverful deployments were scaled to have a minimum 1 instance running at all times due to the associated startup time of 10+ seconds. We barely ever needed to scale up services with most instances only being frequently used by individual users. A vast majority of requests being directed at only a handful of endpoints providing data for map view change events. Breaking up the web server into individual function handlers for each endpoint was a logical step towards a pay-per-use interface for spatial data.

With all transformations and calculations being handled by the database backend our primary performance concern was the memory footprint of each handler and the ability to quickly scale functions for frequent synchronous requests.

There is an excellent article by Brooks Mikkelsen which lists the benefits of a serverless REST API and how to design a HTTP server for Zeit Now.

👉 Designing a Serverless Express.js API using Zeit Now

Node.js HTTP server

The now/node builder provides the IncomingMessage and ServerResponse from the node HTTP server as parameter types to the module export function from each endpoint handler.

Middleware / Endpoint authentication

The Zeit Now CLI and now/node builder are still in beta and some capabilities are yet to be documented and tested in anger. At the time of moving our project from v1 to v2 it was not entirely clear how to use Express middleware with the now/node builder. In order to secure the REST API we built our own authentication logic to intersect all incoming requests. Being stateless, each private request must bear a signed token to be validated by a node implementation of jsonwebtoken.

The root handler for our API should return an application view template (html) from the API.

The handler script which is provided to the now/node builder

Outside the async module exports function we define the authentication module. The auth module will validate a signed IncomingMessage (req) token and finish the ServerResponse (res) by sending a 4** status code to the client. This would occur if a token has expired. Public endpoints do not require a token. The auth module will respond with a login view if a token is required to access private endpoints.

Configuration Caching and RDS Connection Pooling

In order to cache configuration objects and templates we define a const object and an async method to retrieve the templates object outside the handler.

The async module function to retrieve templates will await for all templates to be loaded from local scripts, database or 3rd party service providers before returning the result to the endpoint. A module should resolve immediately with resources such as the API workspace being cached outside the exported module method.

Module script for aync retrieval of templates

The endpoint will await for the templates to be retrieved and assign the returned templates object to the const defined outside the handler.

Modules may require database connection methods. We use node postgres connection pooling for queries to connected databases. The connection pools are also cached outside the module handler.

The following endpoint will cache database connection pools dbs and a layers configuration object outside the handler.

Script for XYZ geoJSON endpoint.

The layer will be queried from a PostGIS table if a request passes authentication. Data will then be sent as geoJSON to the client.

Routing with now.json rewrites, builds, and headers

The now.json configuration defines build scripts for endpoints, HTTP request/response headers, and route rewrites for deployments to the Zeit now platform.

Environment variables defined in the now.json allow node postgres to create connection pools.

XYZ now.json

Builds define a path directory routing structure where the root.js module script in the /api directory will be accessible via host:3000/api/root

Routing can be further defined by using rewrites.

Headers allow us provide additional security headers for all API endpoints.

Debugging in VScode with express.js

Using now dev allows to locally build and serve the API. Logs and Error messages will be sent to the terminal console. Debugging methods with breakpoints and variable inspection in VScode is currently not possible with now dev.

node http server methods used by the now/node builder are fairly similar to the same server methods in express.js.

We can create an express server script to host the same endpoints. If launched in a VScode debug session we can use all the code debug tools.

express.js server script for debugging

Deploying

The API may be deployed to the cloud by providing the now.json to the Zeit now CLI.

👏 👏 👏

I hope this article will be helpful for you if you are building a serverless REST API. This may also provide a better understanding of the Open Source XYZ framework. It certainly will help myself to get feedback which I can feed back into the XYZ documentation.

Big thanks to @paulogdm and the @zeithq team for all the help along the way. It must have taken us a dozen or more Spectrum posts to get here.

--

--

Dennis Bauszus

I am doing some web and map stuff with @GEOLYTIX. Mostly maps on the web.