{"id":4542,"date":"2018-02-08T07:00:16","date_gmt":"2018-02-08T15:00:16","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=4542"},"modified":"2025-06-13T18:45:48","modified_gmt":"2025-06-14T01:45:48","slug":"use-openwhisk-for-faas-with-node-js-and-couchbase-nosql","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","title":{"rendered":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL"},"content":{"rendered":"<p>If you&#8217;ve been keeping up with my content, you&#8217;ll remember that I had written an article titled,\u00a0<a href=\"https:\/\/www.couchbase.com\/blog\/use-aws-lambda-api-gateway-node-js-couchbase-nosql\/\" target=\"_blank\" rel=\"noopener\">Use AWS Lambda and API Gateway with Node.js and Couchbase NoSQL<\/a>. In this article we had explored using Amazon&#8217;s Serverless services to create Lambda functions that interact with Couchbase, our NoSQL database.<\/p>\n<p>However, Lambda isn&#8217;t the only serverless, otherwise known as functions as a service (FaaS), technology on the block. Take <a href=\"https:\/\/openwhisk.apache.org\/\" target=\"_blank\" rel=\"noopener\">Apache OpenWhisk<\/a> for example. With OpenWhisk you can create functions similarly to how you would with Lambda, but deploy them to a more diverse set of locations, the popular being IBM Bluemix.<\/p>\n<p>We&#8217;re going to see how to create serverless functions using OpenWhisk to communicate with our <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener\">Couchbase Server<\/a> database.<\/p>\n<p><!--more--><\/p>\n<p>Going forward, there are a few things to note. You&#8217;ll need to be hosting Couchbase Server somewhere accessible by the outside world. This means that your local computer won&#8217;t work. You&#8217;re going to need Docker so we can compile our dependencies to work with OpenWhisk. Finally, you&#8217;re going to need a Bluemix account, for this example at least.<\/p>\n<h2>Installing the Bluemix CLI Tools for OpenWhisk<\/h2>\n<p>Like I previously mentioned, OpenWhisk is an Apache Foundation project. However, for convenience we&#8217;re going to be using it on IBM&#8217;s Bluemix.<\/p>\n<p>Create an account for the <a href=\"https:\/\/console.bluemix.net\/openwhisk\/\" target=\"_blank\" rel=\"noopener\">IBM Cloud<\/a> if you haven&#8217;t already.<\/p>\n<p>Instead of using a framework tool like Serverless, we&#8217;re going to be using the Bluemix CLI. Download the <a href=\"https:\/\/console.bluemix.net\/openwhisk\/learn\/cli\" target=\"_blank\" rel=\"noopener\">IBM Cloud Functions CLI<\/a> so we can interact with OpenWhisk on IBM.<\/p>\n<p>Before you can start working with your IBM Cloud account, you need to sign in via the CLI. From the command line, execute the following:<\/p>\n<pre class=\"lang:default decode:true \">bx login -a api.ng.bluemix.net -o your_email@example.com -s dev<\/pre>\n<p>When downloading the CLI, you&#8217;ll be given the exact command, but it should look similar to what I&#8217;ve presented above.<\/p>\n<p>Now we can start creating our project.<\/p>\n<h2>Understanding the Project Structure and OpenWhisk Package Creation Process<\/h2>\n<p>If you&#8217;ve never worked with FaaS before, things are done a little differently than building a stand-alone, hardly scalable application.<\/p>\n<p>For example, each endpoint in our FaaS project will be a separate function. Combined, these functions create what is called a package. These functions scale as necessary to meet the changing demand of your application.<\/p>\n<p>With that said, create the following:<\/p>\n<pre class=\"lang:default decode:true \">create\r\n--- package.json\r\n--- create.js\r\nretrieve\r\n--- package.json\r\n--- retrieve.js\r\nupdate\r\n--- package.json\r\n--- update.js\r\ndelete\r\n--- package.json\r\n--- delete.js<\/pre>\n<p>The project should have a directory for each function that we wish to create. Each function will have its own\u00a0<strong>package.json<\/strong> file. Each\u00a0<strong>package.json<\/strong> file can be created by executing the following within each of the directories:<\/p>\n<pre class=\"lang:default decode:true \">npm init -y<\/pre>\n<p>Within each of the\u00a0<strong>package.json<\/strong> files, you&#8217;ll also need to define which file is your function code. For example, open\u00a0<strong>create\/package.json<\/strong> and add or change the following line:<\/p>\n<pre class=\"lang:default decode:true \">\"main\": \"create.js\",<\/pre>\n<p>By setting the <code>main<\/code> file, we are stating which JavaScript file contains our function.<\/p>\n<p>When we start deploying our functions, we&#8217;ll be doing it so they are part of the same package.<\/p>\n<h2>Designing a Function for Creating Data<\/h2>\n<p>Let&#8217;s start development with creating data in our database. Navigate to the\u00a0<strong>create<\/strong> directory and execute the following command from your command line:<\/p>\n<pre class=\"lang:default decode:true \">npm install couchbase uuid joi --save<\/pre>\n<p>The above command will install our function dependencies. We&#8217;ll be using the Couchbase SDK for Node.js, the UUID library for generating unique keys, and the Joi library for validating input.<\/p>\n<p>We will be revisiting the dependency installation, but at least it will keep us going for now.<\/p>\n<p>Now open the project&#8217;s\u00a0<strong>create\/create.js<\/strong> file and include the following:<\/p>\n<pre class=\"lang:default decode:true \">const Couchbase = require(\"couchbase\");\r\nconst UUID = require(\"uuid\");\r\nconst Joi = require(\"joi\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var schema = Joi.object().keys({\r\n        firstname: Joi.string().required(),\r\n        lastname: Joi.string().required(),\r\n        type: Joi.string().forbidden().default(\"person\")\r\n    });\r\n    var data = params;\r\n    var response = {};\r\n    return new Promise((resolve, reject) =&gt; {\r\n        var validation = Joi.validate(data, schema, { stripUnknown: true });\r\n        if(validation.error) {\r\n            response = {\r\n                statusCode: 500,\r\n                body: JSON.stringify(validation.error.details)\r\n            };\r\n            reject(response);\r\n        }\r\n        var id = UUID.v4();\r\n        bucket.insert(id, validation.value, (error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            data.id = id;\r\n            response = {\r\n                body: JSON.stringify(validation.value)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>The above code is a bit much, so we need to figure out what is going on. Let&#8217;s start with the variable that exists outside of our function:<\/p>\n<pre class=\"lang:default decode:true \">var bucket = null;<\/pre>\n<p>It isn&#8217;t the best idea to establish a new connection every time the function is called. Instead, we can keep a global instance of the open Couchbase Bucket and for as long as it exists, use it. Just note that it won&#8217;t always exist because OpenWhisk will destroy functions after a while of inactivity.<\/p>\n<pre class=\"lang:default decode:true \">if(bucket == null) {\r\n    var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n    cluster.authenticate(params.username, params.password);\r\n    bucket = cluster.openBucket(params.bucketName);\r\n}<\/pre>\n<p>Inside our function we check to see if the Bucket is already open. If the Bucket is not open, we establish a connection using parameters passed into the function. When the time comes, we&#8217;ll be defining default parameters which contain this connection information.<\/p>\n<p>Since we&#8217;re creating data, we need to validate that the input is correct.<\/p>\n<pre class=\"lang:default decode:true \">var schema = Joi.object().keys({\r\n    firstname: Joi.string().required(),\r\n    lastname: Joi.string().required(),\r\n    type: Joi.string().forbidden().default(\"person\")\r\n});<\/pre>\n<p>We&#8217;re expecting a <code>firstname<\/code> and <code>lastname<\/code> value to be present. We&#8217;re also expecting a <code>type<\/code> to not be present. We can validate this with the following:<\/p>\n<pre class=\"lang:default decode:true \">var validation = Joi.validate(data, schema, { stripUnknown: true });\r\nif(validation.error) {\r\n    response = {\r\n        statusCode: 500,\r\n        body: JSON.stringify(validation.error.details)\r\n    };\r\n    reject(response);\r\n}<\/pre>\n<p>The <code>stripUnknown<\/code> option will remove data not defined in the scheme. We need to strip data because our input and connection information will exist in the same payload. We don&#8217;t want the connection information to be saved in our documents. If there is a validation error, it will be returned. If there was no validation error, we can proceed to inserting the data.<\/p>\n<pre class=\"lang:default decode:true \">var id = UUID.v4();\r\nbucket.insert(id, validation.value, (error, result) =&gt; {\r\n    if(error) {\r\n        response = {\r\n            body: JSON.stringify({\r\n                code: error.code,\r\n                message: error.message\r\n            })\r\n        };\r\n        reject(response);\r\n    }\r\n    data.id = id;\r\n    response = {\r\n        body: JSON.stringify(validation.value)\r\n    };\r\n    resolve(response);\r\n});<\/pre>\n<p>We can generate a new unique key and save the validated data as a document. The data itself will be returned as a response.<\/p>\n<p>The other functions will follow this same strategy, more or less.<\/p>\n<h2>Designing a Function for Retrieving Data with N1QL<\/h2>\n<p>Now that we have data, let&#8217;s try to retrieve it from the database with a function invocation. Navigate to your\u00a0<strong>retrieve<\/strong> directory and execute the following from the command line:<\/p>\n<pre class=\"lang:default decode:true \">npm install couchbase --save<\/pre>\n<p>Because we won&#8217;t be creating data, we don&#8217;t need to generate unique values or validate any user data. For this reason, we only need the Couchbase SDK for this function.<\/p>\n<p>Open the project&#8217;s\u00a0<strong>retrieve\/retrieve.js<\/strong> file and include the following:<\/p>\n<pre class=\"lang:default decode:true \">const Couchbase = require(\"couchbase\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var response = {};\r\n    var statement = \"SELECT META().id, `\" + bucket._name + \"`.* FROM `\" + bucket._name + \"` WHERE type = 'person'\";\r\n    var query = Couchbase.N1qlQuery.fromString(statement);\r\n    return new Promise((resolve, reject) =&gt; {\r\n        bucket.query(query, (error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            response = {\r\n                body: JSON.stringify(result)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>Let&#8217;s skip over what we&#8217;ve already seen in the previous function and jump to what&#8217;s new. Once we&#8217;re connected to an open Bucket, we can create a N1QL query.<\/p>\n<pre class=\"lang:default decode:true \">var statement = \"SELECT META().id, `\" + bucket._name + \"`.* FROM `\" + bucket._name + \"` WHERE type = 'person'\";\r\nvar query = Couchbase.N1qlQuery.fromString(statement);\r\nreturn new Promise((resolve, reject) =&gt; {\r\n    bucket.query(query, (error, result) =&gt; {\r\n        if(error) {\r\n            response = {\r\n                body: JSON.stringify({\r\n                    code: error.code,\r\n                    message: error.message\r\n                })\r\n            };\r\n            reject(response);\r\n        }\r\n        response = {\r\n            body: JSON.stringify(result)\r\n        };\r\n        resolve(response);\r\n    });\r\n});<\/pre>\n<p>This N1QL query is SQL-like and it will allow us to retrieve all documents that match certain criteria. If there are any errors, return them as a response, otherwise return the result set.<\/p>\n<p>Because we&#8217;re not validating anything, this function for retrieving data was much simpler.<\/p>\n<h2>Designing a Function for Updating Data with Subdocument Mutations<\/h2>\n<p>Now let&#8217;s say that we want to update documents within the database. Instead of retrieving documents, making changes, then saving those changes, we&#8217;re going to submit changes directly to the database and let the database figure things out.<\/p>\n<p>Navigate into the project&#8217;s\u00a0<strong>update<\/strong> directory and execute the following from the command line:<\/p>\n<pre class=\"lang:default decode:true \">npm install couchbase joi --save<\/pre>\n<p>Because we&#8217;re accepting user data, we want to validate that data. We&#8217;re not creating data so we don&#8217;t need to generate any unique keys.<\/p>\n<p>Open the project&#8217;s\u00a0<strong>update\/update.js<\/strong> file and include the following:<\/p>\n<pre class=\"lang:default decode:true \">const Couchbase = require(\"couchbase\");\r\nconst Joi = require(\"joi\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var schema = Joi.object().keys({\r\n        id: Joi.string().required(),\r\n        firstname: Joi.string().optional(),\r\n        lastname: Joi.string().optional()\r\n    });\r\n    var data = params;\r\n    var response = {};\r\n    return new Promise((resolve, reject) =&gt; {\r\n        var validation = Joi.validate(data, schema, { stripUnknown: true });\r\n        if(validation.error) {\r\n            response = {\r\n                statusCode: 500,\r\n                body: JSON.stringify(validation.error.details)\r\n            };\r\n            reject(response);\r\n        }\r\n        var builder = bucket.mutateIn(validation.value.id);\r\n        if(validation.value.firstname) {\r\n            builder.replace(\"firstname\", validation.value.firstname);\r\n        }\r\n        if(validation.value.lastname) {\r\n            builder.replace(\"lastname\", validation.value.lastname);\r\n        }\r\n        builder.execute((error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    statusCode: 500,\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            response = {\r\n                statusCode: 200,\r\n                body: JSON.stringify(validation.value)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>Does the above code look familiar? It should, because we&#8217;re following the same strategy.<\/p>\n<p>Our validation logic is slightly different in this example:<\/p>\n<pre class=\"lang:default decode:true \">var schema = Joi.object().keys({\r\n    id: Joi.string().required(),\r\n    firstname: Joi.string().optional(),\r\n    lastname: Joi.string().optional()\r\n});<\/pre>\n<p>We want to edit a particular document so a key is required. We don&#8217;t know what the user wants to update so we set the properties as optional.<\/p>\n<p>To do updates we&#8217;re going to be doing subdocument operations on our documents. To do this, we can use a mutation builder.<\/p>\n<pre class=\"lang:default decode:true \">var builder = bucket.mutateIn(validation.value.id);\r\nif(validation.value.firstname) {\r\n    builder.replace(\"firstname\", validation.value.firstname);\r\n}\r\nif(validation.value.lastname) {\r\n    builder.replace(\"lastname\", validation.value.lastname);\r\n}<\/pre>\n<p>We provide a document to alter and whatever paths the properties exist at. The paths could be much more complex than the examples used here.<\/p>\n<p>With the set of mutations defined, we can execute them against the database.<\/p>\n<pre class=\"lang:default decode:true \">builder.execute((error, result) =&gt; {\r\n    if(error) {\r\n        response = {\r\n            statusCode: 500,\r\n            body: JSON.stringify({\r\n                code: error.code,\r\n                message: error.message\r\n            })\r\n        };\r\n        reject(response);\r\n    }\r\n    response = {\r\n        statusCode: 200,\r\n        body: JSON.stringify(validation.value)\r\n    };\r\n    resolve(response);\r\n});<\/pre>\n<p>Depending on the result, a response will be returned from the invocation of the function.<\/p>\n<h2>Designing a Function for Removing Data<\/h2>\n<p>We&#8217;re at our final function in a package of CRUD operations. The time has come to delete data from the database.<\/p>\n<p>Navigate to the\u00a0<strong>delete<\/strong> directory and execute the following command:<\/p>\n<pre class=\"lang:default decode:true \">npm install couchbase joi --save<\/pre>\n<p>We&#8217;ll be accepting document keys to be deleted so we&#8217;ll need to validate the input. Likewise we also need the Couchbase SDK to work with the database.<\/p>\n<p>Open the project&#8217;s\u00a0<strong>delete\/delete.js<\/strong> file and include the following JavaScript code:<\/p>\n<pre class=\"lang:default decode:true \">const Couchbase = require(\"couchbase\");\r\nconst Joi = require(\"joi\");\r\n\r\nvar bucket = null;\r\n\r\nfunction main(params) {\r\n    if(bucket == null) {\r\n        var cluster = new Couchbase.Cluster(\"couchbase:\/\/\" + params.host);\r\n        cluster.authenticate(params.username, params.password);\r\n        bucket = cluster.openBucket(params.bucketName);\r\n    }\r\n    var schema = Joi.object().keys({\r\n        id: Joi.string().required()\r\n    });\r\n    var data = params;\r\n    var response = {};\r\n    return new Promise((resolve, reject) =&gt; {\r\n        var validation = Joi.validate(data, schema, { stripUnknown: true });\r\n        if(validation.error) {\r\n            response = {\r\n                statusCode: 500,\r\n                body: JSON.stringify(validation.error.details)\r\n            };\r\n            reject(response);\r\n        }\r\n        bucket.remove(validation.value.id, (error, result) =&gt; {\r\n            if(error) {\r\n                response = {\r\n                    body: JSON.stringify({\r\n                        code: error.code,\r\n                        message: error.message\r\n                    })\r\n                };\r\n                reject(response);\r\n            }\r\n            response = {\r\n                body: JSON.stringify(validation.value)\r\n            };\r\n            resolve(response);\r\n        });\r\n    });\r\n}\r\n\r\nexports.main = main;<\/pre>\n<p>You&#8217;re probably seeing the bigger picture now in regards to function creation with OpenWhisk and Couchbase, so we&#8217;re not going to walk through the above function for deleting documents.<\/p>\n<h2>Packaging and Deploying the Functions to OpenWhisk with Docker<\/h2>\n<p>We have a set of functions ready to go, but we can&#8217;t just package and deploy them to Bluemix. If we did that, we&#8217;d get a bunch of errors. Bluemix uses a special flavor of Linux with a certain architecture. I downloaded the dependencies on my Mac which isn&#8217;t a match.<\/p>\n<p>Remember that article I wrote a while back titled,\u00a0<a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/12\/deploying-native-nodejs-dependencies-aws-lambda\/\" target=\"_blank\" rel=\"noopener\">Deploying Native Node.js Dependencies On AWS Lambda<\/a>? We need to do something similar for OpenWhisk with Docker.<\/p>\n<p>With Docker installed and ready to go, execute the following from the CLI:<\/p>\n<pre class=\"lang:default decode:true \">docker pull openwhisk\/nodejs6action\r\ndocker run -it -v \/Users\/nraboy\/Desktop\/couchbase-openwhisk:\/project openwhisk\/nodejs6action \/bin\/bash<\/pre>\n<p>The above commands will download an appropriate OpenWhisk Docker image for Node.js. Then we deploy a container with that image in interactive terminal mode. This container will also have a mapped volume. I am mapping my local project directory to a directory within the container.<\/p>\n<p>After the command has executed and the container is deployed, you should be in the shell within the container.<\/p>\n<p>For each function, execute the following:<\/p>\n<pre class=\"lang:default decode:true \">cd \/project\/create\r\nnpm install<\/pre>\n<p>Remember, installing dependencies from our host machine isn&#8217;t good enough. We need to compile the dependencies for Bluemix. Docker will compile these dependencies and since the directory is mapped, we can use them from the host machine.<\/p>\n<p>After each functions packages are installed, we can bundle them and deploy them.<\/p>\n<p>From the host machine, create a ZIP archive of each of the functions. The archive should contain the\u00a0<strong>package.json<\/strong> file, the JavaScript file, and the\u00a0<strong>node_modules<\/strong> directory.<\/p>\n<p>If you&#8217;re on a Mac or computer with a ZIP CLI, execute the following:<\/p>\n<pre class=\"lang:default decode:true \">cd create\r\nzip -r create.zip *<\/pre>\n<p>When you have a ZIP of each function, they can be deployed by executing the following:<\/p>\n<pre class=\"lang:default decode:true \">bx wsk action create couchbase\/delete --kind nodejs:default delete.zip -p host ec2-45-236-32-140.compute-1.amazonaws.com -p username demo -p password bluemix -p bucketName example<\/pre>\n<p>I introduced some new things in the above command.<\/p>\n<p>First, we&#8217;re creating a package called\u00a0<strong>couchbase<\/strong> and in this package we have a\u00a0<strong>delete<\/strong> function that is based off the\u00a0<strong>delete.zip<\/strong> file. I&#8217;m also passing some default parameters. These parameters will be our connection information. Since this information is sensitive, we are not passing them when invoking the function, rather creating the function.<\/p>\n<p>Execute a variation of the above command for each of your functions.<\/p>\n<p>To execute your function, try running something like the following:<\/p>\n<pre class=\"lang:default decode:true \">bx wsk action invoke couchbase\/create -p firstname Nic -p lastname Raboy --blocking<\/pre>\n<p>The above command should pass in a few parameters to pass validation. The function is invoked in a blocking manner, and if it succeeds, our data will be saved in the database and returned in the response.<\/p>\n<h2>Conclusion<\/h2>\n<p>You just saw how to create a package of serverless functions for OpenWhisk that communicate with the NoSQL database, <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener\">Couchbase<\/a>. OpenWhisk can be used as an alternative to AWS Lambda, but the two are certainly not the only options available. Regardless on what you choose, functions as a service (FaaS) are very scalable solutions for massive applications.<\/p>\n<p>Want to see another OpenWhisk example? Check out a tutorial I wrote titled,\u00a0<a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/12\/convert-nodejs-restful-api-serverless-openwhisk\/\">Convert a Node.js RESTful API to Serverless with OpenWhisk<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;ve been keeping up with my content, you&#8217;ll remember that I had written an article titled,\u00a0Use AWS Lambda and API Gateway with Node.js and Couchbase NoSQL. In this article we had explored using Amazon&#8217;s Serverless services to create Lambda [&hellip;]<\/p>\n","protected":false},"author":63,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1814,1816,1822],"tags":[2134,2115,2133,1725,2099],"ppma_author":[9032],"class_list":["post-4542","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-couchbase-server","category-node-js","tag-actions","tag-faas","tag-functions","tag-nosql-database","tag-serverless"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL<\/title>\n<meta name=\"description\" content=\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\" \/>\n<meta property=\"og:description\" content=\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-08T15:00:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T01:45:48+00:00\" \/>\n<meta name=\"author\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\",\"datePublished\":\"2018-02-08T15:00:16+00:00\",\"dateModified\":\"2025-06-14T01:45:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\"},\"wordCount\":1857,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"actions\",\"faas\",\"functions\",\"NoSQL Database\",\"serverless\"],\"articleSection\":[\"Application Design\",\"Couchbase Server\",\"Node.js\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\",\"name\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-02-08T15:00:16+00:00\",\"dateModified\":\"2025-06-14T01:45:48+00:00\",\"description\":\"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\/\/www.thepolyglotdeveloper.com\",\"https:\/\/www.facebook.com\/thepolyglotdeveloper\",\"https:\/\/x.com\/nraboy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/nic-raboy-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","description":"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","og_locale":"en_US","og_type":"article","og_title":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","og_description":"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.","og_url":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2018-02-08T15:00:16+00:00","article_modified_time":"2025-06-14T01:45:48+00:00","author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","datePublished":"2018-02-08T15:00:16+00:00","dateModified":"2025-06-14T01:45:48+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"},"wordCount":1857,"commentCount":3,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["actions","faas","functions","NoSQL Database","serverless"],"articleSection":["Application Design","Couchbase Server","Node.js"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","url":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/","name":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2018-02-08T15:00:16+00:00","dateModified":"2025-06-14T01:45:48+00:00","description":"Learn how to create and deploy highly scalable applications as functions using OpenWhisk on Bluemix for FaaS and Couchbase for NoSQL JSON data.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/use-openwhisk-for-faas-with-node-js-and-couchbase-nosql\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Use OpenWhisk for FaaS with Node.js and Couchbase NoSQL"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1","name":"Nic Raboy, Developer Advocate, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/author\/nic-raboy-2\/"}]}},"authors":[{"term_id":9032,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","author_category":"","last_name":"Raboy","first_name":"Nic","job_title":"","user_url":"https:\/\/www.thepolyglotdeveloper.com","description":"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4542","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=4542"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4542\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=4542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=4542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=4542"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=4542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}