{"id":4852,"date":"2018-03-19T11:50:44","date_gmt":"2018-03-19T18:50:44","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=4852"},"modified":"2025-06-13T21:20:32","modified_gmt":"2025-06-14T04:20:32","slug":"timed-tasks-using-couchbase-go","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/","title":{"rendered":"Timed tasks using Couchbase and Go"},"content":{"rendered":"<h5>Alberto Marchetti is a full-stack developer, and author of<a href=\"https:\/\/hydex11.net\/renderscript_parallel_computing_on_android_the_easy_way\" target=\"_blank\" rel=\"noopener noreferrer\">\u00a0\u201c<\/a><a href=\"https:\/\/hydex11.net\/renderscript_parallel_computing_on_android_the_easy_way\" target=\"_blank\" rel=\"noopener noreferrer\">RenderScript: parallel computing on Android, the easy way<\/a>.\u201d\u00a0He is always living on the edge by constantly jumping into the discovery of modern languages and technologies.<\/h5>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignleft wp-image-4851 \" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/03\/photo5834550288516754817-1024x1024.jpg\" alt=\"\" width=\"396\" height=\"396\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-1024x1024.jpg 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-300x300.jpg 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-150x150.jpg 150w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-768x768.jpg 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-65x65.jpg 65w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-50x50.jpg 50w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817-20x20.jpg 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/03\/photo5834550288516754817.jpg 1280w\" sizes=\"auto, (max-width: 396px) 100vw, 396px\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Timed tasks<strong>\u00a0using Couchbase and Go<\/strong><\/h2>\n<p>In this post I\u2019m going to show how you can exploit the Couchbase indexing system to create a timed-tasks distributed system. The example code for the project, together with its run instructions, can be found at <a href=\"https:\/\/github.com\/cmaster11\/cb-blog-timed-tasks\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/github.com\/cmaster11\/cb-blog-timed-tasks<\/a>.<br \/>\n<em>Disclaimer: Because of the complexity of the topic, only relevant code extracts are posted in this page.<\/em><\/p>\n<h2><strong>The concept<\/strong><\/h2>\n<p>Let\u2019s try to define the requirements of such a system:<\/p>\n<ul>\n<li>The main feature of a timed tasks system is to be able to specify when a certain task will be executed in time. This can be achieved by using an ExecuteAt\u00a0field, which will contain the desired execution time (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Unix_time\" target=\"_blank\" rel=\"noopener noreferrer\">Unix time<\/a>, milliseconds-based).<\/li>\n<li>A modern software requirement is that it must support a multi-node environment, which means it needs to be a distributed system. We must then ensure that multiple workers will NOT process the same tasks! We can use a nice Couchbase feature here, <a href=\"https:\/\/www.couchbase.com\/blog\/optimistic-or-pessimistic-locking-which-one-should-you-pick\/\">pessimistic locking<\/a>, which will let a worker fetch a document and lock it down, so that no other workers can process it.<\/li>\n<\/ul>\n<p>The following is a\u00a0possible structure to represent our task:<\/p>\n<pre class=\"lang:default decode:true\">type Task struct {\r\n    Id string\r\n\r\n    \/\/ The desired task execution time\r\n    ExecuteAt int64\r\n\r\n    \/\/ Task-specific content\r\n    Content string\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h2><strong>Couchbase features<\/strong><\/h2>\n<p>First, here\u2019s\u00a0an overview of the\u00a0Couchbase features we\u2019ll be using:<\/p>\n<h3>META()<\/h3>\n<p>Every document in a Couchbase bucket has an associated META()-document, which contains document\u00a0entity-specific information like:<\/p>\n<ul>\n<li>id\u00a0\u2013\u00a0the document key inside the bucket.<\/li>\n<li>cas\u00a0\u2013\u00a0an int64\u00a0number, used by Couchbase to prevent <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/sdk\/concurrent-mutations-cluster.html\" target=\"_blank\" rel=\"noopener noreferrer\">race conditions<\/a>\u00a0while editing documents.<\/li>\n<li>expiration\u00a0\u2013\u00a0when a document is meant to expire, or 0 if it will never expire.<\/li>\n<\/ul>\n<p><em>Hint<\/em>: These fields (e.g., META().cas) <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/n1ql\/n1ql-language-reference\/indexing-meta-info.html\" target=\"_blank\" rel=\"noopener noreferrer\">can be indexed<\/a>\u00a0(starting from Couchbase 5.0).<\/p>\n<h3><strong>CAS (Check and Set)<\/strong><\/h3>\n<p>When fetching a document, its CAS value is returned too, and subsequent calls to alter the document can specify this value to make sure they\u2019re going to edit the desired version of the document.<\/p>\n<p>Example:<\/p>\n<ul>\n<li>Client A fetches a document and its current CAS value is 1234.<\/li>\n<li>Client B edits the document, which alters the CAS value to 5678.<\/li>\n<\/ul>\n<ol>\n<li>If A tries to edit the document without providing the CAS value, the edit will be successful, but changes made by B will be lost.<\/li>\n<li>If A tries to edit the document providing the CAS value (1234), an error will be returned because the current one (5678) is different. Client A will then need to fetch the document again and re-execute the process.<\/li>\n<\/ol>\n<p>The CAS value is an extremely useful tool to ensure\u00a0we\u2019re not replacing or altering a wrong\/newer version of a document, losing its changes.<\/p>\n<h3><strong>Pessimistic locking<\/strong><\/h3>\n<p>Couchbase lets us \u201clock\u201d a document, so that it can only be read and written by one client at a time, using <a href=\"https:\/\/github.com\/couchbase\/gocb\/blob\/v1.3.3\/bucket_crud.go#L18\" target=\"_blank\" rel=\"noopener noreferrer\">gocb.GetAndLock<\/a>\u00a0Go SDK function.<\/p>\n<pre class=\"lang:default decode:true \">\/\/ Lock the document\r\nlockTime := 10 \/\/ seconds\r\nlockedCAS, err := bucket.GetAndLock(documentKey, lockTime, &amp;outStruct)\r\n\r\n\/\/ Unlock it\r\n_, err = bucket.Unlock(documentKey, lockedCAS)<\/pre>\n<p>&nbsp;<\/p>\n<p>When a document is locked, every other request to lock\/mutate\/unlock it will throw an error (it\u2019s still possible to simply get\u00a0the document), unless the correct CAS value is used.<\/p>\n<p>Note: The maximum lock time of a document is 15 seconds, and using a lockTime\u00a0value of 0 will cause the maximum time to be set. This creates a limitation on how long a task can run before being automatically marked as available (by locking timeout).<\/p>\n<p><em>Hint:<\/em>\u00a0While a document is locked, its returned CAS value is -1.<\/p>\n<h2><strong>Indexing and querying<\/strong><\/h2>\n<p>Of note\u00a0two hints put together tell us that we can index a field (META().cas), which turns to -1\u00a0when a document is locked. It also means \u00a0that we can query documents based on this condition!<\/p>\n<h3><strong>The query<\/strong><\/h3>\n<p>Let\u2019s try to define a query to match the requirements:<\/p>\n<ul>\n<li>We want to get a task id, which can be used later to get-and-lock the document: SELECT Id.<\/li>\n<li>The task should not be already locked: WHERE META().cas &lt;&gt; -1.<\/li>\n<li>The task needs to be executed now: WHERE ExecuteAt &lt;= NOW_MILLIS()\u00a0(<a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/current\/n1ql\/n1ql-language-reference\/datefun.html#story-h2-30\" target=\"_blank\" rel=\"noopener noreferrer\">NOW_MILLIS<\/a>\u00a0returns the current Unix time in milliseconds).<\/li>\n<li>We need to fetch the closest task in time, so we want to sort tasks by their execution time: ORDER BY ExecuteAt ASC.<\/li>\n<li>Let\u2019s say for now (!!!) that a worker will want to get only one task to process at a time: LIMIT 1.<\/li>\n<\/ul>\n<p>The result should be similar to this query:<\/p>\n<pre class=\"lang:default decode:true\">SELECT `Id`\r\nFROM `timed_tasks` \/\/ Our bucket\r\nWHERE META().`cas` &lt;&gt; -1\r\nAND `ExecuteAt` &lt;= NOW_MILLIS()\r\nORDER BY `ExecuteAt` ASC\r\nLIMIT 1<\/pre>\n<p>Its execution will return an array similar to:<\/p>\n<pre class=\"lang:default decode:true \">[{\r\n    \"Id\": \"task_id_goes_here\"\r\n}]<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>The index<\/strong><\/h3>\n<p>We can now plan a query-specific index, optimized for the execution of the query we just thought about. Query-specific indexes are a must to improve NoSQL database query performance.<\/p>\n<ul>\n<li>The query is checking that a document is not currently locked:\n<pre class=\"lang:default decode:true \">WHERE META().cas &lt;&gt; -1.<\/pre>\n<\/li>\n<li>Also, it\u2019s directly asking the execution time to be in the past. We then need to index the ExecuteAt\u00a0field.<br \/>\nThe index query could then be the following:<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">CREATE INDEX `idx_timed_task`\r\nON `timed_tasks`\r\n(`ExecuteAt` ASC)\r\nWHERE META().`cas` &lt;&gt; -1<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>Optimizing the query<\/strong><\/h3>\n<p>We can now further optimize the query:<\/p>\n<ul>\n<li>We can tell the query to use our index by providing a <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/n1ql\/n1ql-language-reference\/hints.html\" target=\"_blank\" rel=\"noopener noreferrer\">hint<\/a>\u00a0to it: USE INDEX (idx_timed_task USING GSI).<\/li>\n<li>We can ask Couchbase to wait for the index to be up\u00a0to\u00a0date (usually indexing is an asynchronous process) before executing the query, so that our results will for sure contain unlocked tasks, by providing a <a href=\"https:\/\/developer.couchbase.com\/documentation\/server\/5.1\/indexes\/performance-consistency.html\" target=\"_blank\" rel=\"noopener noreferrer\">consistency<\/a>\u00a0requirement at SDK level: query.Consistency(gocb.RequestPlus).<\/li>\n<\/ul>\n<h2><strong>The flow<\/strong><\/h2>\n<p>A possible flow for the timed task consumer worker loop is:<\/p>\n<ol>\n<li>Query for an available task id.<\/li>\n<li>Get and lock the task.<\/li>\n<li>Process the task.<\/li>\n<li>Delete the task.<\/li>\n<\/ol>\n<h3><strong>Multiple nodes<\/strong><\/h3>\n<p>Let\u2019s think for a second about how a multi-node setup can alter this flow.<\/p>\n<p>If multiple workers are going to query for available tasks concurrently, they\u2019d probably find the same task, and only one of them would be able to process it successfully, while the other workers will have to repeat the loop (execute a new query) to get new tasks.<\/p>\n<p>We can implement then another approach:<\/p>\n<ol>\n<li>Query for available tasks\u00a0ids, limiting the amount of ids to the number of workers.<\/li>\n<li>For each task id, try to lock the task. At first successful lock, go to 4.<\/li>\n<li>If no tasks have been successfully locked, repeat loop.<\/li>\n<li>Process the task.<\/li>\n<li>Delete the task.<\/li>\n<\/ol>\n<p>At its best, every worker will be able to successfully lock one task at first try. At its worse, workers will need to try to lock multiple documents unsuccessfully. The average execution will see workers successfully locking tasks, maybe after trying to lock a few others.<\/p>\n<p>We have to make a compromise between how frequently we want to query the database, and how many failed lock attempts we can support. Generally speaking, trying to lock documents will be much faster than executing N1QL queries.<\/p>\n<h2><strong>The code<\/strong><\/h2>\n<p>Let\u2019s take a look at some relevant code examples:<\/p>\n<h3><strong>The producer<\/strong><\/h3>\n<p>The generation of the task can be summed up in this function:<\/p>\n<pre class=\"lang:default decode:true \">func NewTask(executeAt time.Time, content string) (*Task, error) {\r\n    if executeAt.IsZero() {\r\n        return nil, errors.New(\"executeAt must not be a zero time\")\r\n    }\r\n\r\n    taskUUID, err := uuid.NewV1() \/\/ github.com\/satori\/go.uuid\r\n    if err != nil {\r\n        return nil, err\r\n    }\r\n\r\n    \/\/ Convert time.Time to int64 milliseconds\r\n    executeAtMillis := executeAt.UnixNano() \/ int64(time.Millisecond)\r\n\r\n    task := Task{\r\n        Id:        taskUUID.String(),\r\n        ExecuteAt: executeAtMillis,\r\n        Content:   content,\r\n    }\r\n\r\n    return &amp;task, nil\r\n}\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Once we generate a valid task object, we can simply insert it in our bucket with:<\/p>\n<pre class=\"lang:default decode:true \">_, err := controller.bucket.Insert(task.Id, task, 0)<\/pre>\n<p>&nbsp;<\/p>\n<h3><strong>The consumer<\/strong><\/h3>\n<p>We can get and lock a document by id, using this code:<\/p>\n<pre class=\"lang:default decode:true \">\/\/ Using zero values for lock time will set the maximum time available.\r\ntask := new(Task)\r\nlockedCAS, err := controller.bucket.GetAndLock(taskId, 0, &amp;task)<\/pre>\n<p>A task can be removed using this code:<\/p>\n<pre class=\"lang:default decode:true \">_, err := controller.bucket.Remove(taskId, lockedCAS)<\/pre>\n<p>The main consumer code can be summed up with the following snippet:<\/p>\n<pre class=\"lang:default decode:true \">taskIds, err := couchbaseController.QueryNextTaskIds(consumersCount)\r\n...\r\n\r\nif len(taskIds) == 0 {\r\n    ...\r\n    \/\/ No tasks have been found, restart the loop\r\n}\r\n\r\nvar taskId string\r\nvar task *internal.Task\r\nvar lockedCAS gocb.Cas\r\n\r\nfor _, taskId = range taskIds {\r\n    \/\/ Lock and get the task, so that only this consumer will process it\r\n    task, lockedCAS, err = couchbaseController.GetAndLockTask(taskId)\r\n    if err != nil {\r\n        ...\r\n        \/\/ Error getting the task, proceed to next one in list\r\n        continue\r\n    }\r\n\r\n    \/\/ Successfully locked task!\r\n    \/\/ Move out to process it\r\n    break\r\n}\r\n\r\nif task == nil {\r\n    ...\r\n    \/\/ No tasks could be locked, restart loop\r\n}\r\n\r\n\/\/ Actual processing of the task\r\n\/\/ Improvement: could also return an error, which would let the task be\r\n\/\/ processed by another worker later.\r\nprocessTask(task)\r\n\r\n\/*\r\nRemove the task from Couchbase.\r\nThe task will be currently locked, which means we need to provide the\r\ncurrent CAS value, so that the producer is authorized to remove it.\r\n *\/\r\nerr = couchbaseController.RemoveTask(taskId, lockedCAS)\r\n...\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2><strong>Conclusion<\/strong><\/h2>\n<p>In this post we\u2019ve seen a way to create a reliable distributed timed tasks system using Couchbase and Go.<\/p>\n<p>This system could be further developed by:<\/p>\n<ul>\n<li>Support for processing errors.<\/li>\n<li>Implementing a retry feature (if processing fails, reschedule the task in the future).<\/li>\n<li>Improving the locking logic by:\n<ul>\n<li>Tuning the maximum number of returned task ids (instead of the default workers count).<\/li>\n<li>Supporting a task processing duration of more than 15 seconds (the maximum lock time of a document in Couchbase).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Thank you for your time, and happy developing!<\/p>\n<p style=\"text-align: center\"><em>This post is part of the <a href=\"https:\/\/www.couchbase.com\/community\/community-writers-program\/\" target=\"_blank\" rel=\"noopener noreferrer\">Community Writing program<\/a><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alberto Marchetti is a full-stack developer, and author of\u00a0\u201cRenderScript: parallel computing on Android, the easy way.\u201d\u00a0He is always living on the edge by constantly jumping into the discovery of modern languages and technologies. &nbsp; Timed tasks\u00a0using Couchbase and Go In [&hellip;]<\/p>\n","protected":false},"author":53,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,1820],"tags":[],"ppma_author":[9026],"class_list":["post-4852","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-golang"],"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>Timed tasks using Couchbase and Go - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.\" \/>\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\/timed-tasks-using-couchbase-go\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Timed tasks using Couchbase and Go\" \/>\n<meta property=\"og:description\" content=\"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-03-19T18:50:44+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T04:20:32+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/06\/CB-Blog_red-black-big.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Laura Czajkowski, Developer Community Manager, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/06\/CB-Blog_red-black-big.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Laura Czajkowski, Developer Community Manager, 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\/timed-tasks-using-couchbase-go\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\"},\"author\":{\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220\"},\"headline\":\"Timed tasks using Couchbase and Go\",\"datePublished\":\"2018-03-19T18:50:44+00:00\",\"dateModified\":\"2025-06-14T04:20:32+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\"},\"wordCount\":1311,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Couchbase Server\",\"GoLang\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\",\"name\":\"Timed tasks using Couchbase and Go - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-03-19T18:50:44+00:00\",\"dateModified\":\"2025-06-14T04:20:32+00:00\",\"description\":\"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#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\/timed-tasks-using-couchbase-go\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Timed tasks using Couchbase and Go\"}]},{\"@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\/5f1a0ece4e644bc8c037686fbc8f3220\",\"name\":\"Laura Czajkowski, Developer Community Manager, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g\",\"caption\":\"Laura Czajkowski, Developer Community Manager, Couchbase\"},\"description\":\"Laura Czajkowski is the Snr. Developer Community Manager at Couchbase overseeing the community. She\u2019s responsible for our monthly developer newsletter.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/laura-czajkowski\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Timed tasks using Couchbase and Go - The Couchbase Blog","description":"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.","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\/timed-tasks-using-couchbase-go\/","og_locale":"en_US","og_type":"article","og_title":"Timed tasks using Couchbase and Go","og_description":"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.","og_url":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/","og_site_name":"The Couchbase Blog","article_published_time":"2018-03-19T18:50:44+00:00","article_modified_time":"2025-06-14T04:20:32+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/06\/CB-Blog_red-black-big.png","type":"image\/png"}],"author":"Laura Czajkowski, Developer Community Manager, Couchbase","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/06\/CB-Blog_red-black-big.png","twitter_misc":{"Written by":"Laura Czajkowski, Developer Community Manager, Couchbase","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/"},"author":{"name":"Laura Czajkowski, Developer Community Manager, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/5f1a0ece4e644bc8c037686fbc8f3220"},"headline":"Timed tasks using Couchbase and Go","datePublished":"2018-03-19T18:50:44+00:00","dateModified":"2025-06-14T04:20:32+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/"},"wordCount":1311,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Couchbase Server","GoLang"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/","url":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/","name":"Timed tasks using Couchbase and Go - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2018-03-19T18:50:44+00:00","dateModified":"2025-06-14T04:20:32+00:00","description":"See how to use the Couchbase indexing system to create a timed-tasks distributed system using Couchbase and Go. Also, check some Couchbase features.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/timed-tasks-using-couchbase-go\/#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\/timed-tasks-using-couchbase-go\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Timed tasks using Couchbase and Go"}]},{"@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\/5f1a0ece4e644bc8c037686fbc8f3220","name":"Laura Czajkowski, Developer Community Manager, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9deb07d5daaa00220534c31768bc4409","url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","caption":"Laura Czajkowski, Developer Community Manager, Couchbase"},"description":"Laura Czajkowski is the Snr. Developer Community Manager at Couchbase overseeing the community. She\u2019s responsible for our monthly developer newsletter.","url":"https:\/\/www.couchbase.com\/blog\/author\/laura-czajkowski\/"}]}},"authors":[{"term_id":9026,"user_id":53,"is_guest":0,"slug":"laura-czajkowski","display_name":"Laura Czajkowski, Developer Community Manager, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bc8eebaf25cbe39bc12fd7b1ef92550becc3953ab877a3f0285a59ec2d30b754?s=96&d=mm&r=g","author_category":"","last_name":"Czajkowski","first_name":"Laura","job_title":"","user_url":"","description":"Laura Czajkowski is the Snr. Developer Community Manager at Couchbase overseeing the community. She\u2019s responsible for our monthly developer newsletter."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4852","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\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=4852"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4852\/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=4852"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=4852"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=4852"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=4852"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}