{"id":3901,"date":"2017-08-29T07:00:39","date_gmt":"2017-08-29T14:00:39","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=3901"},"modified":"2025-06-13T18:46:00","modified_gmt":"2025-06-14T01:46:00","slug":"developing-user-profile-store-golang-nosql-database","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/","title":{"rendered":"Developing a User Profile Store with Golang and a NoSQL Database"},"content":{"rendered":"<p>Remember the tutorial series I wrote in regards to <a href=\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\" target=\"_blank\" rel=\"noopener noreferrer\">creating a user profile store with Node.js and NoSQL<\/a>? That tutorial covered a lot of ground, from creating a RESTful API with Node.js, handling user sessions, data modeling, and of course storing data associated to users.<\/p>\n<p>What if we wanted to take the same concepts and apply them with Golang instead of JavaScript with Node.js?<\/p>\n<p>We&#8217;re going to see how to develop a user profile store with Golang and <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase Server<\/a> that acts as a modular replacement to the Node.js alternative.<\/p>\n<p><!--more--><\/p>\n<p>Going forward, we&#8217;re going to assume that you have Go installed and configured, as well as Couchbase Server. It is not important if you&#8217;ve seen the <a href=\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\" target=\"_blank\" rel=\"noopener noreferrer\">Node.js version of this tutorial<\/a> because we&#8217;re going to revisit everything.<\/p>\n<p>In case you&#8217;re unfamiliar with what a user profile store is or what it does, it is simply a solution for storing information about users and information associated to users. Take for example a blog. A blog might have numerous authors which are technically users. Each author will write content and that content will be associated to the particular user that wrote it. Each author will have their own method of signing into the blog as well.<\/p>\n<p>Because user data models can change so frequently, using a NoSQL database with a flexible storage model is often more effective than an RDBMS alternative. More information on the data modeling aspect can be found in this article,\u00a0<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>, written by Kirk Kirkconnell.<\/p>\n<h2>Golang User Management to Create a New Project<\/h2>\n<p>We&#8217;re going to spend all of our time in a single Go file. Somewhere in your <strong>$GOPATH<\/strong>, create a file called <strong>main.go<\/strong>.<\/p>\n<p>We&#8217;re also going to need a few dependencies, for Couchbase as well as other packages. From the command line, execute the following:<\/p>\n<pre class=\"lang:default decode:true \">go get github.com\/couchbase\/gocb\r\ngo get github.com\/gorilla\/context\r\ngo get github.com\/gorilla\/handlers\r\ngo get github.com\/gorilla\/mux\r\ngo get github.com\/satori\/go.uuid<\/pre>\n<p>The above dependencies will allow us to communicate with Couchbase Server, generate UUID values, and create a RESTful API with cross origin resource sharing (CORS) handling.<\/p>\n<p>The next step is to throw down some boilerplate code for our project. Open the project&#8217;s\u00a0<strong>main.go<\/strong> file and include the following:<\/p>\n<pre class=\"lang:default decode:true \">package main\r\n\r\nimport (\r\n\t\"encoding\/json\"\r\n\t\"fmt\"\r\n\t\"log\"\r\n\t\"net\/http\"\r\n\t\"strings\"\r\n\t\"time\"\r\n\r\n\t\"golang.org\/x\/crypto\/bcrypt\"\r\n\r\n\t\"github.com\/couchbase\/gocb\"\r\n\t\"github.com\/gorilla\/context\"\r\n\t\"github.com\/gorilla\/handlers\"\r\n\t\"github.com\/gorilla\/mux\"\r\n\tuuid \"github.com\/satori\/go.uuid\"\r\n)\r\n\r\ntype Account struct {\r\n\tType     string `json:\"type,omitempty\"`\r\n\tPid      string `json:\"pid,omitempty\"`\r\n\tEmail    string `json:\"email,omitempty\"`\r\n\tPassword string `json:\"password,omitempty\"`\r\n}\r\n\r\ntype Profile struct {\r\n\tType      string `json:\"type,omitempty\"`\r\n\tFirstname string `json:\"firstname,omitempty\"`\r\n\tLastname  string `json:\"lastname,omitempty\"`\r\n}\r\n\r\ntype Session struct {\r\n\tType string `json:\"type,omitempty\"`\r\n\tPid  string `json:\"pid,omitempty\"`\r\n}\r\n\r\ntype Blog struct {\r\n\tType      string `json:\"type,omitempty\"`\r\n\tPid       string `json:\"pid,omitempty\"`\r\n\tTitle     string `json:\"title,omitempty\"`\r\n\tContent   string `json:\"content,omitempty\"`\r\n\tTimestamp int    `json:\"timestamp,omitempty\"`\r\n}\r\n\r\nvar bucket *gocb.Bucket\r\n\r\nfunc Validate(next http.HandlerFunc) http.HandlerFunc {}\r\n\r\nfunc RegisterEndpoint(w http.ResponseWriter, req *http.Request) {}\r\nfunc LoginEndpoint(w http.ResponseWriter, req *http.Request) {}\r\nfunc AccountEndpoint(w http.ResponseWriter, req *http.Request) {}\r\nfunc BlogsEndpoint(w http.ResponseWriter, req *http.Request) {}\r\nfunc BlogEndpoint(w http.ResponseWriter, req *http.Request) {}\r\n\r\nfunc main() {\r\n\tfmt.Println(\"Starting the Go server...\")\r\n\trouter := mux.NewRouter()\r\n\tcluster, _ := gocb.Connect(\"couchbase:\/\/localhost\")\r\n\tbucket, _ = cluster.OpenBucket(\"default\", \"\")\r\n\trouter.HandleFunc(\"\/account\", RegisterEndpoint).Methods(\"POST\")\r\n\trouter.HandleFunc(\"\/login\", LoginEndpoint).Methods(\"POST\")\r\n\trouter.HandleFunc(\"\/account\", Validate(AccountEndpoint)).Methods(\"GET\")\r\n\trouter.HandleFunc(\"\/blogs\", Validate(BlogsEndpoint)).Methods(\"GET\")\r\n\trouter.HandleFunc(\"\/blog\", Validate(BlogEndpoint)).Methods(\"POST\")\r\n\tlog.Fatal(http.ListenAndServe(\":3000\", handlers.CORS(handlers.AllowedHeaders([]string{\"X-Requested-With\", \"Content-Type\", \"Authorization\"}), handlers.AllowedMethods([]string{\"GET\", \"POST\", \"PUT\", \"HEAD\", \"OPTIONS\"}), handlers.AllowedOrigins([]string{\"*\"}))(router)))\r\n}<\/pre>\n<p>In the above, you&#8217;ll notice that we&#8217;ve created a few data structures to represent our data. We&#8217;re going with the idea of a blogging platform.<\/p>\n<p>The application will have five RESTful API endpoints, a validator method for our user sessions, and a global Couchbase variable that will allow us to access our open instance anywhere in the application.<\/p>\n<pre class=\"lang:default decode:true \">router.HandleFunc(\"\/account\", Validate(AccountEndpoint)).Methods(\"GET\")\r\nrouter.HandleFunc(\"\/blogs\", Validate(BlogsEndpoint)).Methods(\"GET\")\r\nrouter.HandleFunc(\"\/blog\", Validate(BlogEndpoint)).Methods(\"POST\")<\/pre>\n<p>Notice that the above three endpoints have the <code>Validate<\/code> function attached to them. This means that the user must have authenticated and be providing a valid session to progress. In this sense the <code>Validate<\/code> function acts as a middleware.<\/p>\n<p>Because we plan to query for data, more specifically, blog articles to a particular user, we need to have an index created. Using the web dashboard, Couchbase CLI, or Go application, execute the following:<\/p>\n<pre class=\"lang:default decode:true \">CREATE INDEX `blogbyuser` ON `default`(type, pid);<\/pre>\n<p>The above index will allow us to query by a <code>type<\/code> property as well as a <code>pid<\/code> property.<\/p>\n<p>Now we can start filling in the holes for each of our API endpoints.<\/p>\n<h2>Allowing Users to Register New Information with the Profile Store<\/h2>\n<p>Since we have no users in the profile store as of right now, it would make sense to create an endpoint that supports the creation of new users.<\/p>\n<p>It is good practice to never store username and password type credential information with actual user information. For this reason, creating a new user means creating a <strong>profile<\/strong> document as well as an <strong>account<\/strong> document. The <strong>account<\/strong> document will reference the <strong>profile<\/strong> document. Both will be modeled after our Go data structures that we saw in the boilerplate code.<\/p>\n<p>In the\u00a0<strong>main.go<\/strong> file, add the following:<\/p>\n<pre class=\"lang:default decode:true \">func RegisterEndpoint(w http.ResponseWriter, req *http.Request) {\r\n\tvar data map[string]interface{}\r\n\t_ = json.NewDecoder(req.Body).Decode(&amp;data)\r\n\tid := uuid.NewV4().String()\r\n\tpasswordHash, _ := bcrypt.GenerateFromPassword([]byte(data[\"password\"].(string)), 10)\r\n\taccount := Account{\r\n\t\tType:     \"account\",\r\n\t\tPid:      id,\r\n\t\tEmail:    data[\"email\"].(string),\r\n\t\tPassword: string(passwordHash),\r\n\t}\r\n\tprofile := Profile{\r\n\t\tType:      \"profile\",\r\n\t\tFirstname: data[\"firstname\"].(string),\r\n\t\tLastname:  data[\"lastname\"].(string),\r\n\t}\r\n\t_, err := bucket.Insert(id, profile, 0)\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\t_, err = bucket.Insert(data[\"email\"].(string), account, 0)\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\tjson.NewEncoder(w).Encode(account)\r\n}<\/pre>\n<p>There are a few important things happening in the above endpoint code.<\/p>\n<p>First we are accepting JSON data that was send with the POST body from the client request. We are generating a unique id for the <strong>profile<\/strong> document and hashing the password for safe keeping with BCrypt.<\/p>\n<p>When it comes to actually saving the data, the user profile will receive a unique id while the account will receive an email address as the id and a reference to the profile id within the document.<\/p>\n<p>By following this approach, the <strong>account<\/strong> document could easily be extended into other forms of credentials. For example, the account document could be rebranded as <strong>basicauth<\/strong>, and we could have Facebook, Twitter, etc., that reference the profile information.<\/p>\n<h2>Implementing a Session Token for Users<\/h2>\n<p>Signing into the application via our two documents is a little different. It is never a good idea to pass around the username and password more than is absolutely necessary.<\/p>\n<p>For this reason, it is a good idea to use a session token that represents the user. This token can expire and holds no sensitive information.<\/p>\n<p>Take the following sign-in code for the\u00a0<strong>main.go<\/strong> file:<\/p>\n<pre class=\"lang:default decode:true \">func LoginEndpoint(w http.ResponseWriter, req *http.Request) {\r\n\tvar data Account\r\n\tvar account Account\r\n\t_ = json.NewDecoder(req.Body).Decode(&amp;data)\r\n\t_, err := bucket.Get(data.Email, &amp;account)\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\terr = bcrypt.CompareHashAndPassword([]byte(account.Password), []byte(data.Password))\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\tsession := Session{\r\n\t\tType: \"session\",\r\n\t\tPid:  account.Pid,\r\n\t}\r\n\tvar result map[string]interface{}\r\n\tresult = make(map[string]interface{})\r\n\tresult[\"sid\"] = uuid.NewV4().String()\r\n\t_, err = bucket.Insert(result[\"sid\"].(string), &amp;session, 3600)\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\tjson.NewEncoder(w).Encode(result)\r\n}<\/pre>\n<p>When the email and password is passed to this endpoint, the <strong>account<\/strong> document is retrieved based on the email that was provided. The hashed password inside this document is then compared against the unhashed password.<\/p>\n<p>If the credentials are valid, a <strong>session<\/strong> document is created. This session document has a unique key, but references the key of the <strong>profile<\/strong> document. An expiration time is also added to the document. When the expiration time passes, the document will be automatically removed from Couchbase without any application or user intervention. This helps secure the account.<\/p>\n<p>With the accounts functional, we need to worry about associating information with the users.<\/p>\n<h2>Managing User Information in the Profile Store via a Session Token<\/h2>\n<p>When a user tries to do something specific to his or herself, we need to validate that they are who they should be and that the information they are changing is applied to the correct person.<\/p>\n<p>This is where the session token validation middleware comes into play.<\/p>\n<pre class=\"lang:default decode:true \">func Validate(next http.HandlerFunc) http.HandlerFunc {\r\n\treturn http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {\r\n\t\tauthorizationHeader := req.Header.Get(\"authorization\")\r\n\t\tif authorizationHeader != \"\" {\r\n\t\t\tbearerToken := strings.Split(authorizationHeader, \" \")\r\n\t\t\tif len(bearerToken) == 2 {\r\n\t\t\t\tvar session Session\r\n\t\t\t\t_, err := bucket.Get(bearerToken[1], &amp;session)\r\n\t\t\t\tif err != nil {\r\n\t\t\t\t\tw.WriteHeader(401)\r\n\t\t\t\t\tw.Write([]byte(err.Error()))\r\n\t\t\t\t\treturn\r\n\t\t\t\t}\r\n\t\t\t\tcontext.Set(req, \"pid\", session.Pid)\r\n\t\t\t\tbucket.Touch(bearerToken[1], 0, 3600)\r\n\t\t\t\tnext(w, req)\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tw.WriteHeader(401)\r\n\t\t\tw.Write([]byte(\"An authorization header is required\"))\r\n\t\t\treturn\r\n\t\t}\r\n\t})\r\n}<\/pre>\n<p>Every request to one of our three special endpoints will require an authorization header that contains a bearer token with the session id. No bearer token means the request will fail. Incorrect or expired bearer token means the request will fail.<\/p>\n<p>Validation will exchange the session id for a profile id to be used in the next step of the request.<\/p>\n<p>Starting simple, let&#8217;s say we want to return the profile information for a particular user. Our endpoint might look like the following:<\/p>\n<pre class=\"lang:default decode:true \">func AccountEndpoint(w http.ResponseWriter, req *http.Request) {\r\n\tpid := context.Get(req, \"pid\").(string)\r\n\tvar profile Profile\r\n\t_, err := bucket.Get(pid, &amp;profile)\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\tjson.NewEncoder(w).Encode(profile)\r\n}<\/pre>\n<p>The <code>pid<\/code> is passed from the validation middleware and a lookup is done with the profile id.<\/p>\n<p>Not so difficult so far right?<\/p>\n<p>Let&#8217;s kick it up a notch and introduce some N1QL queries into our project. Let&#8217;s say we want to get all blog posts for a particular user. This will make use of our index as well as the SQL-like queries.<\/p>\n<pre class=\"lang:default decode:true \">func BlogsEndpoint(w http.ResponseWriter, req *http.Request) {\r\n\tvar n1qlParams []interface{}\r\n\tn1qlParams = append(n1qlParams, context.Get(req, \"pid\").(string))\r\n\tquery := gocb.NewN1qlQuery(\"SELECT `\" + bucket.Name() + \"`.* FROM `\" + bucket.Name() + \"` WHERE type = 'blog' AND pid = $1\")\r\n\tquery.Consistency(gocb.RequestPlus)\r\n\trows, err := bucket.ExecuteN1qlQuery(query, n1qlParams)\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\tvar row Blog\r\n\tvar result []Blog\r\n\tfor rows.Next(&amp;row) {\r\n\t\tresult = append(result, row)\r\n\t\trow = Blog{}\r\n\t}\r\n\trows.Close()\r\n\tif result == nil {\r\n\t\tresult = make([]Blog, 0)\r\n\t}\r\n\tjson.NewEncoder(w).Encode(result)\r\n}<\/pre>\n<p>In the above endpoint code, we take the <code>pid<\/code> from the validation middleware and add it as a parameter for our parameterized query.<\/p>\n<p>We&#8217;ll iterate through the <code>QueryResults<\/code> returned from the query and add them to a <code>[]Blog<\/code> variable. If no results were found, we can just return an empty slice.<\/p>\n<p>Doing direct lookups based on key will always be faster than N1QL queries, but N1QL queries are very useful when you need to query by property information.<\/p>\n<p>The final endpoint isn&#8217;t any different than we&#8217;ve already seen:<\/p>\n<pre class=\"lang:default decode:true \">func BlogEndpoint(w http.ResponseWriter, req *http.Request) {\r\n\tvar blog Blog\r\n\t_ = json.NewDecoder(req.Body).Decode(&amp;blog)\r\n\tblog.Type = \"blog\"\r\n\tblog.Pid = context.Get(req, \"pid\").(string)\r\n\tblog.Timestamp = int(time.Now().Unix())\r\n\t_, err := bucket.Insert(uuid.NewV4().String(), blog, 0)\r\n\tif err != nil {\r\n\t\tw.WriteHeader(401)\r\n\t\tw.Write([]byte(err.Error()))\r\n\t\treturn\r\n\t}\r\n\tjson.NewEncoder(w).Encode(blog)\r\n}<\/pre>\n<p>In the above code, we accept a POST body from the client as well as the <code>pid<\/code> from the validation middleware. That information is then saved into Couchbase.<\/p>\n<h2>Conclusion<\/h2>\n<p>You just saw how to create a basic user profile store, or in this case, a blogging platform, using the Go programming language and <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener noreferrer\">Couchbase Server<\/a>. This is an alternative tutorial to a <a href=\"https:\/\/www.couchbase.com\/blog\/creating-user-profile-store-with-node-js-nosql-database\/\" target=\"_blank\" rel=\"noopener noreferrer\">previous tutorial<\/a> that I had written on the same subject, but with Node.js.<\/p>\n<p>Want to take this tutorial to the next level? Check out how to create a <a href=\"https:\/\/www.couchbase.com\/blog\/creating-front-end-user-profile-store-angular-typescript\/\" target=\"_blank\" rel=\"noopener noreferrer\">web client front-end with Angular<\/a> or a <a href=\"https:\/\/www.couchbase.com\/blog\/bringing-user-profile-store-mobile-nativescript-angular\/\" target=\"_blank\" rel=\"noopener noreferrer\">mobile client front-end with NativeScript<\/a>.<\/p>\n<p>For more information on using Couchbase with Golang, 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>Remember the tutorial series I wrote in regards to creating a user profile store with Node.js and NoSQL? That tutorial covered a lot of ground, from creating a RESTful API with Node.js, handling user sessions, data modeling, and of course [&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,1820],"tags":[1393,1560,1572,1725,2019,2024],"ppma_author":[9032],"class_list":["post-3901","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-best-practices-and-tutorials","category-couchbase-server","category-golang","tag-api","tag-bcrypt","tag-database","tag-nosql-database","tag-profile-store","tag-session"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.0 (Yoast SEO v26.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Golang + NoSQL Database Management for User Profile Store<\/title>\n<meta name=\"description\" content=\"This Couchbase post shows how to develop a user profile store with Golang and Couchbase Server acting as a modular replacement to the Node.js alternative.\" \/>\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\/developing-user-profile-store-golang-nosql-database\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Developing a User Profile Store with Golang and a NoSQL Database\" \/>\n<meta property=\"og:description\" content=\"This Couchbase post shows how to develop a user profile store with Golang and Couchbase Server acting as a modular replacement to the Node.js alternative.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-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-08-29T14:00:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T01:46:00+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=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Developing a User Profile Store with Golang and a NoSQL Database\",\"datePublished\":\"2017-08-29T14:00:39+00:00\",\"dateModified\":\"2025-06-14T01:46:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/\"},\"wordCount\":1360,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"API\",\"bcrypt\",\"database\",\"NoSQL Database\",\"profile store\",\"session\"],\"articleSection\":[\"Application Design\",\"Best Practices and Tutorials\",\"Couchbase Server\",\"GoLang\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/\",\"name\":\"Golang + NoSQL Database Management for User Profile Store\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2017-08-29T14:00:39+00:00\",\"dateModified\":\"2025-06-14T01:46:00+00:00\",\"description\":\"This Couchbase post shows how to develop a user profile store with Golang and Couchbase Server acting as a modular replacement to the Node.js alternative.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-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\/developing-user-profile-store-golang-nosql-database\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Developing a User Profile Store with Golang 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":"Golang + NoSQL Database Management for User Profile Store","description":"This Couchbase post shows how to develop a user profile store with Golang and Couchbase Server acting as a modular replacement to the Node.js alternative.","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\/developing-user-profile-store-golang-nosql-database\/","og_locale":"en_US","og_type":"article","og_title":"Developing a User Profile Store with Golang and a NoSQL Database","og_description":"This Couchbase post shows how to develop a user profile store with Golang and Couchbase Server acting as a modular replacement to the Node.js alternative.","og_url":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2017-08-29T14:00:39+00:00","article_modified_time":"2025-06-14T01:46:00+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":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Developing a User Profile Store with Golang and a NoSQL Database","datePublished":"2017-08-29T14:00:39+00:00","dateModified":"2025-06-14T01:46:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/"},"wordCount":1360,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["API","bcrypt","database","NoSQL Database","profile store","session"],"articleSection":["Application Design","Best Practices and Tutorials","Couchbase Server","GoLang"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/","url":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/","name":"Golang + NoSQL Database Management for User Profile Store","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2017-08-29T14:00:39+00:00","dateModified":"2025-06-14T01:46:00+00:00","description":"This Couchbase post shows how to develop a user profile store with Golang and Couchbase Server acting as a modular replacement to the Node.js alternative.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-nosql-database\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/developing-user-profile-store-golang-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\/developing-user-profile-store-golang-nosql-database\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Developing a User Profile Store with Golang 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\/3901","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=3901"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/3901\/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=3901"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=3901"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=3901"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=3901"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}