{"id":3868,"date":"2017-07-31T07:00:28","date_gmt":"2017-07-31T14:00:28","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=3868"},"modified":"2025-06-13T20:15:14","modified_gmt":"2025-06-14T03:15:14","slug":"creating-user-profile-store-with-node-js-nosql-database","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/","title":{"rendered":"Create a User Profile Store with Node.js and a NoSQL Database"},"content":{"rendered":"<p>There are many use-cases for NoSQL databases, one that I encounter frequently is creating a user profile store and session. This use-case lends itself to a <a href=\"https:\/\/www.couchbase.com\/resources\/why-nosql\/\">NoSQL database<\/a>. Profiles often need to be flexible and accept data changes. While possible in an RDBMS, it would require more work to maintain the data with performance penalties.<\/p>\n<p>Kirk Kirkconnell wrote a high-level example to create a user profile store and session with Couchbase: <a href=\"https:\/\/www.couchbase.com\/blog\/user-profile-store-advanced-data-modeling\/\" target=\"_blank\" rel=\"noopener noreferrer\">User Profile Store: Advanced Data Modeling<\/a>. We&#8217;re going to expand on these concepts and implement a user profile store using Node.js databases and <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase Server<\/a>.<\/p>\n<p><strong>This tutorial has been updated as of January 4th, 2021 by <a href=\"https:\/\/www.couchbase.com\/blog\/author\/eric-bishard\/\">Eric Bishard<\/a> to work with the Couchbase <a href=\"https:\/\/docs.couchbase.com\/nodejs-sdk\/3.1\/hello-world\/start-using-sdk.html\">NodeJS SDK 3<\/a>!<\/strong><\/p>\n<p><!--more--><\/p>\n<p>Before we write some code, let&#8217;s figure out what we&#8217;re trying to accomplish.<\/p>\n<p>When it comes to managing user data, we need a way to create a user profile store and session and associate other documents with them. Let&#8217;s define some rules around this user profile store concept:<\/p>\n<ul>\n<li>Store account data like username and password in a profile document.<\/li>\n<li>Pass sensitive user data with each user action request.<\/li>\n<li>Use a session that expires after a set amount of time.<\/li>\n<li>Stored session documents with an expiry limit.<\/li>\n<\/ul>\n<p>We can manage all of this with the following API endpoints:<\/p>\n<ul>\n<li>POST \/account &#8211; Create a new user profile with account information<\/li>\n<li>POST \/login &#8211; Validate account information<\/li>\n<li>GET \/account &#8211; Get account information<\/li>\n<li>POST \/blog &#8211; Create a new blog entry associated to a user<\/li>\n<li>GET \/blogs &#8211; Get all blog entries for a particular user<\/li>\n<\/ul>\n<p>These endpoints will be part of our API backend utilizing the Couchbase Server Node.js SDK (this article has been updated to use version 3.1.x).<\/p>\n<h2>Creating the API with Node and Express<\/h2>\n<p>Let&#8217;s create a project directory for our Node.js app and install our dependencies.<\/p>\n<pre class=\"lang:default decode:true\">mkdir blog-api \u00a0&amp;&amp;\u00a0 cd blog-api \u00a0&amp;&amp;\u00a0 npm init -y\r\nnpm install couchbase express body-parser uuid bcryptjs cors --save<\/pre>\n<p>This creates a working directory for our project and initializes a new Node project. Our dependencies include the <a href=\"https:\/\/docs.couchbase.com\/nodejs-sdk\/3.1\/hello-world\/start-using-sdk.html\">Node.js SDK for Couchbase<\/a> and Express Framework and other utility libraries like <code>body-parser<\/code> to accept JSON data via POST requests, <code>uuid<\/code> for generating unique keys and <code>bcryptjs<\/code> to hash our passwords to deter malicious users.<\/p>\n<p>Let&#8217;s bootstrap our application with a <strong>server.js<\/strong> file:<\/p>\n<pre class=\"lang:default decode:true \">const couchbase = require('couchbase')\r\nconst express = require('express')\r\nconst uuid = require('uuid')\r\nconst bodyParser = require('body-parser')\r\nconst bcrypt = require('bcryptjs')\r\nconst cors = require('cors')\r\n\r\nconst app = express()\r\n\r\napp.use(cors())\r\napp.use(bodyParser.json())\r\napp.use(bodyParser.urlencoded({ extended: true }))\r\n\r\nconst cluster = new couchbase.Cluster('couchbase:\/\/localhost', {\r\n  username: 'Administrator', password: 'password'\r\n})\r\nconst bucket = cluster.bucket('blog')\r\nconst collection = bucket.defaultCollection()\r\n\r\nconst server = app.listen(3000, () =&gt; console.info(`Running on port ${server.address().port}...`))<\/pre>\n<p>The above code requires our dependencies and initializes an Express app running on port 3000 against Couchbase Server using a bucket named <code>blog<\/code>.<\/p>\n<p>We also need to create an index in Couchbase Server because we&#8217;ll be using the N1QL query language for one of our endpoints. If we access our Couchbase Server web console running locally on <strong>localhost:8091<\/strong>, we can click on the <strong>Query<\/strong> tab and execute this statement in the Query Editor:<\/p>\n<pre class=\"lang:default decode:true\">CREATE INDEX `blogbyuser` ON `default`(type, pid);<\/pre>\n<p>Since we will obtain all blog posts for a particular profile id, we&#8217;ll get better performance using this specific index rather than a general primary index. Primary Indexes are not recommended for production-level code.<\/p>\n<h2>Saving a New User to the Profile Store<\/h2>\n<p>We know that a user profile can have any information describing a user. Info like address, phone, social media info, etc. It is never a good idea to store account credentials in the same document as our basic profile information. We&#8217;ll need a minimum of two documents for every user, let&#8217;s take a look at how those documents will be structured.<\/p>\n<p>Our profile document will have a key that we will refer to in our related documents. This key is an auto-generated UUID: <code>b181551f-071a-4539-96a5-8a3fe8717faf<\/code>.<\/p>\n<p>Our Profile document will have a JSON value that includes two properties: <code>email<\/code>\u00a0and a <code>type<\/code> property. The <code>type<\/code> property is an important indicator that describes our document similar to how a table organizes records in a relational database. This is a standard convention in a document database.<\/p>\n<pre class=\"lang:default decode:true\">{\r\n  \"type\": \"profile\",\r\n  \"email\": \"user1234@gmail.com\"\r\n}<\/pre>\n<p>The account document associated with our profile will have a key that is equal to our user&#8217;s email:<br \/>\n<code>user1234@gmail.com<\/code> and this document will have a <code>type<\/code>, as well as a <code>pid<\/code> referring to the key of our profile document along with <code>email<\/code> and hashed <code>password<\/code>.<\/p>\n<pre class=\"lang:default decode:true\">{\r\n  \"type\": \"account\",\r\n  \"pid\": \"b181551f-071a-4539-96a5-8a3fe8717faf\",\r\n  \"email\": \"user1234@gmail.com\",\r\n  \"password\": \"$2a$10$tZ23pbQ1sCX4BknkDIN6NekNo1p\/Xo.Vfsttm.USwWYbLAAspeWsC\"\r\n}<\/pre>\n<p>Great, we have established a model for each document and a strategy for relating those documents without database constraints.<\/p>\n<h2>An Endpoint for Account Creation<\/h2>\n<p>Add the following code to our <code>server.js<\/code> file:<\/p>\n<pre class=\"lang:default decode:true\">app.post(\"\/account\", async (request, response) =&gt; {\r\n  if (!request.body.email) {\r\n    return response.status(401).send({ \"message\": \"An `email` is required\" })\r\n  } else if (!request.body.password) {\r\n    return response.status(401).send({ \"message\": \"A `password` is required\" })\r\n  }\r\n\r\n  const id = uuid.v4()\r\n  const account = {\r\n    \"type\": \"account\",\r\n    \"pid\": id,\r\n    \"email\": request.body.email,\r\n    \"password\": bcrypt.hashSync(request.body.password, 10)\r\n  }\r\n  const profile = {\r\n    \"type\": \"profile\",\r\n    \"email\": request.body.email\r\n  }\r\n\r\n  await collection.insert(id, profile)\r\n    .then(async () =&gt; {\r\n      await collection.insert(request.body.email, account)\r\n        .then((result) =&gt; {\r\n          result.pid = id\r\n          return response.send(result)\r\n        })\r\n        .catch(async (e) =&gt; {\r\n          await collection.remove(id)\r\n            .then(() =&gt; {\r\n              console.error(`account creation failed, removed: ${id}`)\r\n              return response.status(500).send(e)\r\n            })\r\n            .catch(e =&gt; response.status(500).send(e))\r\n        })\r\n    })\r\n    .catch(e =&gt; response.status(500).send(e))\r\n})<\/pre>\n<p>Let&#8217;s break this code down.<\/p>\n<p>First, we check that both an <code>email<\/code> and <code>password<\/code> exist in the request.<\/p>\n<p>Next, we create an <code>account<\/code> object and <code>profile<\/code> object based on the data that was sent in the request. The <code>pid<\/code> that we&#8217;re saving into the\u00a0<code>account<\/code> object is a unique key. It will be set as the document key for our <code>profile<\/code> object.<\/p>\n<p>The <strong>account<\/strong> document uses the email as it&#8217;s key. In the future, if other account details are needed (like alternate email, social login, etc.) we can associate other documents to the profile.<\/p>\n<p>Rather than saving the password in the <code>account<\/code> object as plain text, we hash it with <a href=\"https:\/\/www.npmjs.com\/package\/bcrypt\">Bcrypt<\/a>. The password is stripped from the <code>profile<\/code> object for security. For more info on password hashing, check out <a href=\"https:\/\/www.couchbase.com\/blog\/hashing-passwords-stored-in-couchbase-server-with-nodejs\/\" target=\"_blank\" rel=\"noopener noreferrer\">this tutorial<\/a>.<\/p>\n<p>With the data ready, we can insert it into Couchbase. The goal of this save is to be all or nothing. We want both the <strong>account<\/strong> and <strong>profile<\/strong> documents to be created successfully, otherwise roll it all back. Depending on the success, we&#8217;ll return some info to the client.<\/p>\n<p>We could have used N1QL queries for inserting the data, but it&#8217;s easier to use CRUD operations with no penalty on performance.<\/p>\n<h2>Using Session Tokens for Sensitive Data<\/h2>\n<p>With the user profile and account created, we want the user to sign in and start doing activities that will store data and associate it with them.<\/p>\n<p>We want to log in and establish a session that will be stored in the database referencing our user profile. This document will eventually expire and be removed from the database.<\/p>\n<p>The session model will look like the following:<\/p>\n<pre class=\"lang:default decode:true\">{\r\n  \"type\": \"session\",\r\n  \"id\": \"ce0875cb-bd27-48eb-b561-beee33c9f405\",\r\n  \"pid\": \"b181551f-071a-4539-96a5-8a3fe8717faf\"\r\n}<\/pre>\n<p>This document, like the others, has a different <code>type<\/code>. Just like with the <strong>account<\/strong> document, it has a <code>pid<\/code> property that references a user profile.<\/p>\n<p>The code that makes this possible is in the <strong>login<\/strong> endpoint:<\/p>\n<pre class=\"lang:default decode:true\">app.post(\"\/login\", async (request, response) =&gt; {\r\n  if (!request.body.email) {\r\n    return response.status(401).send({ \"message\": \"An `email` is required\" })\r\n  } else if (!request.body.password) {\r\n    return response.status(401).send({ \"message\": \"A `password` is required\" })\r\n  }\r\n\r\n  await collection.get(request.body.email)\r\n    .then(async (result) =&gt; {\r\n      if (!bcrypt.compareSync(request.body.password, result.value.password)) {\r\n        return response.status(500).send({ \"message\": \"Password invalid\" })\r\n      }\r\n      var session = {\r\n        \"type\": \"session\",\r\n        \"id\": uuid.v4(),\r\n        \"pid\": result.value.pid\r\n      }\r\n      await collection.insert(session.id, session, { \"expiry\": 3600 })\r\n        .then(() =&gt; response.send({ \"sid\": session.id }))\r\n        .catch(e =&gt; response.status(500).send(e))\r\n    })\r\n    .catch(e =&gt; response.status(500).send(e))\r\n})<\/pre>\n<p>After validating the incoming data we do an account lookup by email address. If data comes back for the email, we can compare the incoming password with the hashed password returned in the account lookup. Provided this succeeds, we can create a new session for the user.<\/p>\n<p>Unlike the previous insert operation, we set a document expiration of an hour (3600 s). If the expiration isn&#8217;t refreshed, the document will disappear. This is good because it forces the user to sign in again and get a new session. This session token will be passed with every future request instead of the password.<\/p>\n<h2>Managing a User Session with Tokens<\/h2>\n<p>We want to get information about our user profile as well as associate new things to the profile. For this, we confirm authority through the session.<\/p>\n<p>We can confirm the session is valid using middleware. A Middleware function can be added to any Express endpoint. This validation is a simple function that will have access to our endpoint&#8217;s HTTP request:<\/p>\n<pre class=\"lang:default decode:true\">const validate = async(request, response, next) =&gt; {\r\n  const authHeader = request.headers[\"authorization\"]\r\n  if (authHeader) {\r\n    bearerToken = authHeader.split(\" \")\r\n    if (bearerToken.length == 2) {\r\n      await collection.get(bearerToken[1])\r\n        .then(async(result) =&gt; {\r\n          request.pid = result.value.pid\r\n          await collection.touch(bearerToken[1], 3600)\r\n            .then(() =&gt; next())\r\n            .catch((e) =&gt; console.error(e.message))\r\n        })\r\n        .catch((e) =&gt; response.status(401).send({ \"message\": \"Invalid session token\" }))\r\n    }\r\n  } else {\r\n    response.status(401).send({ \"message\": \"An authorization header is required\" })\r\n  }\r\n}<\/pre>\n<p>Here we are checking the request for an authorization header. If we have a valid bearer token with session id (sid), we can do a lookup. The session document has the profile id in it. If the session lookup is successful, we save the profile id (pid) in the request.<\/p>\n<p>Next, we refresh the session expiration and move through the middleware and back to the endpoint. If the session doesn&#8217;t exist, no profile id will be passed and the request will fail.<\/p>\n<p>Now we can use our middleware to get information about our profile in our account endpoint:<\/p>\n<pre class=\"lang:default decode:true\">app.get(\"\/account\", validate, async (request, response) =&gt; {\r\n  try {\r\n    await collection.get(request.pid)\r\n      .then((result) =&gt; response.send(result.value))\r\n      .catch((e) =&gt; response.status(500).send(e))\r\n  } catch (e) {\r\n    console.error(e.message)\r\n  }\r\n})<\/pre>\n<p>Notice the <code>validate<\/code> happens first and then the rest of the request. The <code>request.pid<\/code> was established by the middleware and it will get us a particular profile document for that id.<\/p>\n<p>Next, we create an endpoint to add a blog article for the user:<\/p>\n<pre class=\"lang:default decode:true \">app.post(\"\/blog\", validate, async(request, response) =&gt; {\r\n  if(!request.body.title) {\r\n    return response.status(401).send({ \"message\": \"A `title` is required\" })\r\n  } else if(!request.body.content) {\r\n    return response.status(401).send({ \"message\": \"A `content` is required\" })\r\n  }\r\n  var blog = {\r\n    \"type\": \"blog\",\r\n    \"pid\": request.pid,\r\n    \"title\": request.body.title,\r\n    \"content\": request.body.content,\r\n    \"timestamp\": (new Date()).getTime()\r\n  }\r\n  const uniqueId = uuid.v4()\r\n  collection.insert(uniqueId, blog)\r\n    .then(() =&gt; response.send(blog))\r\n    .catch((e) =&gt; response.status(500).send(e))\r\n})<\/pre>\n<p>Assuming the middleware succeeded, we create a blog object with a specific <code>type<\/code> and <code>pid<\/code>. Then we can save it to the database.<\/p>\n<p>Querying for all blog posts by a particular user isn&#8217;t too much different:<\/p>\n<pre class=\"lang:default decode:true \">app.get(\"\/blogs\", validate, async(request, response) =&gt; {\r\n  try {\r\n    const query = `SELECT * FROM \\`blog\\` WHERE type = 'blog' AND pid = $PID;`\r\n    const options = { parameters: { PID: request.pid } }\r\n    await cluster.query(query, options)\r\n      .then((result) =&gt; response.send(result.rows))\r\n      .catch((e) =&gt; response.status(500).send(e))\r\n  } catch (e) {\r\n    console.error(e.message)\r\n  }\r\n})<\/pre>\n<p>Because we need to query by document property rather than document key, we&#8217;ll use a N1QL query and index we previously created.<\/p>\n<p>The document <code>type<\/code> and <code>pid<\/code> are passed into the query returning all documents for that particular profile.<\/p>\n<h2>Conclusion<\/h2>\n<p>You just saw how to create a user profile store and session using Node.js and NoSQL. This is a great follow-up to Kirk&#8217;s high-level explanation in his <a href=\"https:\/\/www.couchbase.com\/blog\/user-profile-store-advanced-data-modeling\/\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a>.<\/p>\n<p>As previously mentioned, the <strong>account<\/strong> documents could represent a form of login credentials where you could have a document for basic authentication (Facebook authentication, etc.) referring to the same profile document. Instead of using a UUID for the session, a JSON Web Token (JWT) or maybe something more secure could be used.<\/p>\n<p>The <a href=\"https:\/\/www.couchbase.com\/blog\/creating-front-end-user-profile-store-angular-typescript\/\">next tutorial in this series will help us create a client front-end<\/a> for this API.<\/p>\n<p>The finished code, Postman collections, and environment variables available in the <a href=\"https:\/\/github.com\/couchbaselabs\/couchbase-nodejs-blog-api\">couchbaselabs \/ couchbase-nodejs-blog-api<\/a> repo on GitHub.<\/p>\n<p>For more information on using Couchbase with Node.js, check out the <a href=\"https:\/\/www.couchbase.com\/developers\/\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase Developer Portal<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are many use-cases for NoSQL databases, one that I encounter frequently is creating a user profile store and session. This use-case lends itself to a NoSQL database. Profiles often need to be flexible and accept data changes. While possible [&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,1815,1816,9327,1822],"tags":[1572,1543,1725,2019,2020],"ppma_author":[9032],"class_list":["post-3868","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-best-practices-and-tutorials","category-couchbase-server","category-javascript","category-node-js","tag-database","tag-javascript","tag-nosql-database","tag-profile-store","tag-users"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>User Profile Store: Create with Node.js and NoSQL Database<\/title>\n<meta name=\"description\" content=\"Profiles often need to be flexible and accept data changes. Find out how to implement a user profile store using Node.js databases and Couchbase Server.\" \/>\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\/creating-user-profile-store-with-node-js-nosql-database\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Create a User Profile Store with Node.js and a NoSQL Database\" \/>\n<meta property=\"og:description\" content=\"Profiles often need to be flexible and accept data changes. Find out how to implement a user profile store using Node.js databases and Couchbase Server.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\" \/>\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=\"2017-07-31T14:00:28+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:15:14+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=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Create a User Profile Store with Node.js and a NoSQL Database\",\"datePublished\":\"2017-07-31T14:00:28+00:00\",\"dateModified\":\"2025-06-14T03:15:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\"},\"wordCount\":1520,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"database\",\"javascript\",\"NoSQL Database\",\"profile store\",\"users\"],\"articleSection\":[\"Application Design\",\"Best Practices and Tutorials\",\"Couchbase Server\",\"JavaScript\",\"Node.js\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\",\"name\":\"User Profile Store: Create with Node.js and NoSQL Database\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-07-31T14:00:28+00:00\",\"dateModified\":\"2025-06-14T03:15:14+00:00\",\"description\":\"Profiles often need to be flexible and accept data changes. Find out how to implement a user profile store using Node.js databases and Couchbase Server.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#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\/creating-user-profile-store-with-node-js-nosql-database\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Create a User Profile Store with Node.js and a NoSQL Database\"}]},{\"@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":"User Profile Store: Create with Node.js and NoSQL Database","description":"Profiles often need to be flexible and accept data changes. Find out how to implement a user profile store using Node.js databases and Couchbase Server.","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\/creating-user-profile-store-with-node-js-nosql-database\/","og_locale":"en_US","og_type":"article","og_title":"Create a User Profile Store with Node.js and a NoSQL Database","og_description":"Profiles often need to be flexible and accept data changes. Find out how to implement a user profile store using Node.js databases and Couchbase Server.","og_url":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2017-07-31T14:00:28+00:00","article_modified_time":"2025-06-14T03:15:14+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":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Create a User Profile Store with Node.js and a NoSQL Database","datePublished":"2017-07-31T14:00:28+00:00","dateModified":"2025-06-14T03:15:14+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/"},"wordCount":1520,"commentCount":1,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["database","javascript","NoSQL Database","profile store","users"],"articleSection":["Application Design","Best Practices and Tutorials","Couchbase Server","JavaScript","Node.js"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/","url":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/","name":"User Profile Store: Create with Node.js and NoSQL Database","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-07-31T14:00:28+00:00","dateModified":"2025-06-14T03:15:14+00:00","description":"Profiles often need to be flexible and accept data changes. Find out how to implement a user profile store using Node.js databases and Couchbase Server.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/#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\/creating-user-profile-store-with-node-js-nosql-database\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Create a User Profile Store with Node.js and a NoSQL Database"}]},{"@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\/3868","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=3868"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/3868\/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=3868"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=3868"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=3868"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=3868"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}