Function as a Service (FaaS) commonly referred as serverless computing, feels like the answer to every engineer’s prayers. Simple functions, doing only one small thing and running in infrastructure that scales automatically for a small price, or even for free ðŸ˜!
Webtask is the Function as a Service implementation from the Auth0 team. It’s perfect for prototyping and easy to get started with. They just released their Serverless integration last week.
I’m working with Serverless on my current project, and I’ve wanted to take Webtask for a spin for a while, so I decided this was the perfect time for it.
In a few minutes, I had a REST API, deployed, and running with the help of Express, RethinkDB, Webtask, and Serverless.
Getting started ðŸ
Install the serverless framework and create a new project:
Go into the project’s folder and add the dependencies with NPM:
- express and body-parser will handle routing and JSON responses.
- webtask-tools wraps the express app and binds it to the webtask handler.
- rethinkdbdash is a RethinkDB driver; it has some cool features like connection pooling, an easier interface, and outstanding performance.
Update serverless.yml. Change the service name and add the IP of the RethinkDB server:
The only differences from the default config should be the service name and the environment and defaults options.
The options tell the provider (webtasks in this case) to set RETHINKDB_SERVER as an environment variable and to take its value from either the environment (env), an option from the command line when deploying (--rethinkdb-server) or, if neither is set, from the defaults section.
The API will be running from Auth0’s FaaS infrastructure. RethinkDB needs to be reachable from the internet. I launched a Digital Ocean instance for that.
The final step is to set up a Webtask account:
Show me the code! 🤓
At this point, there is already a Function that can be deployed, run and tested. Give it a try:
It is important to run npm update to install all packages before deploying a function. Dependencies will be pulled from node_modules and uploaded with the function.
The service is running already and zero code. Wow! That is really something!
I realized that this was an excellent first approach to the FaaS paradigm. Definitely easier than setting up an account for AWS λ.
Now into the actual code…
Express + RethinkDB
Like most express apps, start by adding express, body-parser, and webtask-tools. Create the app and add the database as a middleware to all routes:
The RethinkDB instance is now available as db through every endpoint.
The API
- GET /: Retrieves all documents from RethinkDB.
- GET /🆔 Returns a particular document with the given id.
It is a simplistic version with no filtering and basic pagination.
The endpoint will get the response from RethinkDB and return it to the client. If anything goes wrong, it will send the error instead.
- POST /: Creates a new document.
- PUT /: Updates an existing document.
Creating and modifying data is just as simple.
The endpoint gets the JSON from the request and saves it into the shares table. The code is almost the same for both functions.
RethinkDB has support for upserts. When the conflict option is set to update if the body of the request has an existing id it will replace the document. The default behavior is to throw an error if the document with that id exists, which is what the POSTs method is doing.
With returnChanges, the query will return an Array with the resulting changes of the operation in a special object with two properties: new_val and old_val. We use new_val to return the upserted item in the response. In the case of a POST, the object will include the id of the new document.
RethinkDB accepts an Array or an Item when inserting. Lines 6 and 11 normalize the response. If the request had an array, it would return an array with the changes. If it were just one item, it would return only one item.
Besides returning the actual data, it includes the response from RethinkDB. It contains an object with helpful information that looks like this:
"response": {
"changes": [
{
"new_val": {
"id": "044ec21c-78b9-47aa-9eb6-e7e5658237db",
"name": "Tania ðŸ˜"
},
"old_val": {
"id": "044ec21c-78b9-47aa-9eb6-e7e5658237db",
"name": "Tania"
}
}
],
"deleted": 0,
"errors": 0,
"inserted": 0,
"replaced": 1,
"skipped": 0,
"unchanged": 0
}
It can be helpful for the requester to know what happened to the data.
- DELETE /🆔 Removes the document with the given id from the table.
The endpoint gets the id from the request, and ask RethinkDB to remove that document. If anything goes wrong (i.e., the id doesn’t exist) it sends the error back to the client.
That’s all. A fully working –barebones – function as a service-based REST API. The code is straightforward. Small functions that are easy to read and understand.
Next steps will be adding Authentication to the requests and some business logic so the service is more helpful.
I will continue working on it and will elaborate about it in another post.
Webtask and Serverless make it easy to start “dipping your toes” into the Function as a Service world. It focuses around NodeJS with only two event sources HTTP Requests and Scheduled events. Compared to AWS Lambda it’s faster to get started and easier to approach.
Webtask’s free tier is limited to a request per second. But that should be enough for testing; maybe even for a basic service.
More resources 📚
- Webtask.io, the FaaS from the Auth0 guys. It’s easy and straightforward. Works with Node 8 out of the box and it takes less than a minute to get started. Super useful to get started with Slack hooks, Bots, and APIs. It has a fully-featured Web Editor that makes things even simpler. It has real-time logs, 500k of JSON storage, a cron-like scheduler, and Auth0 support is baked in.
- Serverless is a toolkit to work with serverless architectures from any provider (AWS Lambda, Google Functions, Azure Functions, OpenWhisk, Webtask, etc.). With the help of its Event Gateway, you can even combine different providers and make them all work together.
- RethinkDB is an Open Source NoSQL Database with a very nice querying language (ReQL) and advanced features like clustering, near-linear scaling, and real-time feeds. It’s my go-to NoSQL data store.
- Thinky a Javascript ORM for RethinkDB. An easier way to map skinny JSON objects to RethinkDB documents.
Thanks to Rafa Salazar, David Núñez, Andres Cespedes and Martin Moscosa for helping with this article.
Top comments (4)
Hey Eduardo, I came across your weshare-webtask project on Github and thought that since you're interested in trying out FaaS platforms you'd like to checkout Clay, we're working on making it really easy to create an https endpoint without having to do any configuration and then allow you to find and re-use functions that you and others have created. Would love to hear what you think!
One comment, in terms of installing dependencies. When you use the Webtasks provider you actually don't have to run "npm install". We install npm dependencies from the cloud and don't upload them, so you just have to have the module entries in your package.json and it will work.
Hey Eduardo- really like the use of using express here to handle routing! Haven't come across that routing method in Serverless functions before. Does it work with other providers like AWS?
Awesome post! Thanks for trying out Serverless with Webtasks and for the feedback. We're looking forward to seeing more posts :-).