{"id":9083,"date":"2020-08-12T08:39:57","date_gmt":"2020-08-12T15:39:57","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=9083"},"modified":"2025-06-13T22:39:26","modified_gmt":"2025-06-14T05:39:26","slug":"eventing-improvements-timers-handlers-and-statistics","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/","title":{"rendered":"Eventing Improvements: Timers, Handlers and Statistics"},"content":{"rendered":"<p><span style=\"font-weight: 400\">With the release of Couchbase 6.6 the Eventing Service has major improvements in functionality.<\/span><\/p>\n<p>We\u2019ve introduced new Eventing Timers that can be cancelled using the cancelTimer() function, or by creating a new timer with the same reference identifier as an existing timer. Recurring timers are also fully supported, and can easily be used to create repetitive logic by using a timer callback to create fresh timers. Timer scheduling enables timers to be created for days, weeks, or years in the future with no adverse performance impact. The OnDelete Handler now indicates if a document was deleted or expired using the new \u201coptions\u201d parameter. Key Eventing statistics in the UI are now co-located with each Functions lifecycle control.<\/p>\n<p>Together these enhancements simplify the effort and code required to make robust business logic.<\/p>\n<h3>Prerequisites<\/h3>\n<p>In this article we will be introducing key <a href=\"https:\/\/www.couchbase.com\/products\/eventing\">Eventing<\/a> improvements added to the latest GA release, i.e. Couchbase version 6.6.0, and for each item we provide a working basic example.\u00a0 <em>However, please understand that none of the Eventing Functions provided in this article will work &#8220;as-is&#8221; in earlier versions of the Couchbase server without significant\u00a0changes and complex work arounds<\/em>.<\/p>\n<p>If you are not familiar with Couchbase or the Eventing service please walk through GET STARTED and one Eventing example specifically refer to the following:<\/p>\n<ul>\n<li>Setup a working Couchbase 6.6.0 server as per the directions in <a href=\"https:\/\/docs.couchbase.com\/server\/current\/getting-started\/start-here.html\">Start Here!<\/a><\/li>\n<li>Understand both basic Eventing concepts and how to deploy a basic Eventing Function as per the directions in the <a href=\"https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-examples-docarchive.html\">Document Archival<\/a> example.<\/li>\n<\/ul>\n<h3>Eventing Timers can now be Cancelled<\/h3>\n<p>With the addition of the cancelTimer() function, or by creating a new Eventing Timer with the same reference identifier as an existing timer active Timers that have yet to fire can be canceled.\u00a0 This enhancement simplifies the code required to make robust business logic.<\/p>\n<p>Developers no longer are forced to add fields and logic and do additional checking to ensure a Timer being fired is not &#8220;stale&#8221; and superseded by a newer Timer.<\/p>\n<h4>Example:<\/h4>\n<ul>\n<li>Create a &#8220;source&#8221; bucket and a &#8220;metadata&#8221; bucket for Eventing.<\/li>\n<li>Deploy this function (code below).<\/li>\n<li>Create a document in the source bucket with:\n<pre class=\"font:monospace font-size:18 line-height:24 toolbar-overlay:false striped:false marking:false ranges:false nums:false nums-toggle:false lang:default decode:true\">KEY user_scoreboard::1 and DATA {\"type\": \"user_scoreboard\", \"id\": 1}<\/pre>\n<\/li>\n<li>Inspect the logs after a minute.<\/li>\n<li>Delete the document with key &#8220;user_scoreboard::1&#8221;.<\/li>\n<li>Inspect the logs after a minute.<\/li>\n<li>Undeploy this function.<\/li>\n<\/ul>\n<pre class=\"toolbar-overlay:false lang:js decode:true\">function UserInactivityCallback(context) {\r\n    log('user was inactive for 10 minutes', context.docId);\r\n    \/*\r\n    * take some actions ...\r\n    *\/\r\n}\r\n\r\nfunction OnUpdate(doc, meta) {\r\n    if (doc.type != 'user_scoreboard') return;\r\n    \/\/ Create a timestamp 600 seconds from now\r\n    var tenMinutesFromNow = new Date(); \/\/ Get current time &amp; add 600 sec. to it.\r\n    tenMinutesFromNow.setSeconds(tenMinutesFromNow.getSeconds() + 600);\r\n\r\n    \/\/ Every mutation to the user's scoreboard will result in a new Timer but\r\n    \/\/ the old timers will be canceled as they have the same identifier, meta.id.\r\n    createTimer(UserInactivityCallback, tenMinutesFromNow, meta.id, {\r\n        \"docId\": meta.id\r\n    });\r\n}\r\n\r\nfunction OnDelete(meta, options) {\r\n    if (!(meta.id.startsWith(\"user_scoreboard:\"))) return;\r\n    log('user scoreboard was deleted for', meta.id);\r\n    \/\/ remove the timer as there is no related document anymore.\r\n    cancelTimer(UserInactivityCallback,meta.id);\r\n    \/*\r\n    * take some actions ...\r\n    *\/\r\n}<\/pre>\n<h3>Recurring Eventing Timers are now fully supported<\/h3>\n<p>Recurring Timers are fully supported, i.e. a function that is invoked by a timer callback can reliably create fresh Timers.\u00a0 This update allows a single Eventing Function to reliably implement complex recurring events creating new timers from within the callback of another timer.<\/p>\n<p>Previously a co-Function was required to reliably create a recurring series of Timers (left image), the 6.6 release simplifies the code needed to implement recurring (or scheduled) business logic (right image).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-8730\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/04\/ev_cr_1u_design_choices-1.png\" alt=\"Eventing cron update\" width=\"1479\" height=\"649\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/04\/ev_cr_1u_design_choices-1.png 1479w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/04\/ev_cr_1u_design_choices-1-300x132.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/04\/ev_cr_1u_design_choices-1-1024x449.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/04\/ev_cr_1u_design_choices-1-768x337.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/04\/ev_cr_1u_design_choices-1-20x9.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/04\/ev_cr_1u_design_choices-1-1320x579.png 1320w\" sizes=\"auto, (max-width: 1479px) 100vw, 1479px\" \/><\/p>\n<h4>Example:<\/h4>\n<ul>\n<li>Create a &#8220;source&#8221; bucket and a &#8220;metadata&#8221; bucket for Eventing.<\/li>\n<li>Make an Bucket alias in the Function&#8217;s setting as &#8220;src_bkt&#8221; to the source bucket in mode read+write.<\/li>\n<li>Deploy this function (code below).<\/li>\n<li>Create a document in the source bucket with:\n<pre class=\"font:monospace font-size:18 line-height:24 toolbar-overlay:false striped:false marking:false ranges:false nums:false nums-toggle:false lang:default decode:true\">KEY recurring_timer::1 and DATA {\"type\": \"recurring_timer\", \"id\": 1, \"active\": true}<\/pre>\n<\/li>\n<li>Inspect the logs after a minute.<\/li>\n<li>Inspect the logs after several minutes.<\/li>\n<li>Alter the document with key &#8220;recurring_timer::1&#8221; and change the field &#8220;active&#8221; to false as follows:<\/li>\n<li>\n<pre class=\"font:monospace font-size:18 line-height:24 toolbar-overlay:false toolbar-hide:false toolbar-delay:false striped:false marking:false ranges:false nums:false nums-toggle:false lang:default decode:true\">KEY recurring_timer::1 and DATA {\"type\": \"recurring_timer\", \"id\": 1, \"active\": false}<\/pre>\n<\/li>\n<li>Inspect the logs after a minute.<\/li>\n<li>Undeploy this function.<\/li>\n<\/ul>\n<pre class=\"toolbar-overlay:false lang:js decode:true\">function CreateRecurringTimer(context) {\r\n    log('From CreateRecurringTimer: creating timer', context.mode, context.id);\r\n    \/\/ Create a timestamp 30 seconds from now\r\n    var thirtySecFromNow = new Date(); \/\/ Get current time &amp; add 30 sec. to it.\r\n    thirtySecFromNow.setSeconds(thirtySecFromNow.getSeconds() + 30);\r\n    \/\/ Create a document to use as out for our context\r\n    createTimer(RecurringTimerCallback, thirtySecFromNow, context.id, context);\r\n}\r\n\r\nfunction RecurringTimerCallback(context) {\r\n    log('From RecurringTimerCallback: timer fired', context);\r\n\r\n    \/*\r\n    * do any sort of recurring work here, just update a date_stamp in a document\r\n    * written back to the source bucket (but with the ID prefixed whit \"cur_\")\r\n    *\/\r\n    src_bkt[\"cur_\" + context.id] = { \"last_update\": new Date() };\r\n\r\n    \/\/ rearm the timer\r\n    CreateRecurringTimer({ \"id\": context.id, \"mode\": \"via_callback\" })\r\n}\r\n\r\nfunction OnUpdate(doc, meta) {\r\n    \/\/ You would typically filter to mutations of interest\r\n    if (doc.type !== 'recurring_timer') return;\r\n    if (doc.active === false) {\r\n        if (cancelTimer(RecurringTimerCallback, meta.id)) {\r\n            log('From OnUpdate: canceled active Timer, doc.active', doc.active, meta.id);\r\n        } else {\r\n            log('From OnUpdate: no active Timer to cancel, doc.active', doc.active, meta.id);\r\n        }\r\n    } else {\r\n        log('From OnUpdate: create\/overwrite doc.active', doc.active, meta.id);\r\n        CreateRecurringTimer({  \"id\": meta.id, \"mode\": \"via_onupdate\" });\r\n    }\r\n}<\/pre>\n<h3>Timers can be created days\/weeks\/years in the future<\/h3>\n<p><span style=\"font-weight: 400\">One timer or a million timers can be created with no adverse performance impact on an otherwise idle Eventing system. This ability opens up use cases for long term notifications and customer re-engagement programs.<\/span><\/p>\n<p><a id=\"#footnote_1_src\"><\/a>In the 6.5.X releases creating a few thousand Timers in the future (as in one hour+) in an otherwise idle system resulted in a growing number of metadata bucket operations which impacted performance and could eventually block mutations for a the given Eventing Function.<a href=\"#footnote_1\"><sup>[1]<\/sup><\/a><\/p>\n<p><a id=\"#footnote_2_src\"><\/a>Note on a cancelTimer() operation or overwriting an existing Timer by reference there will be a temporary documents in the Eventing &#8220;metadata&#8221; bucket, eventually these documents will be purged.<a href=\"#footnote_2\"><sup>[2]<\/sup><\/a><\/p>\n<h4>Example:<\/h4>\n<p>Demonstrate the creation of a lot of Eventing Timers (in this case 50,000) and schedule them well into the future (by 96 hours) and then cancel the entire set (or allowed them all to fire the callback routine <em>TimerCallback<\/em>).<\/p>\n<ul>\n<li>Create a &#8220;source&#8221; bucket and a &#8220;metadata&#8221; bucket for Eventing.<\/li>\n<li>Deploy this function (code below).<\/li>\n<li>Create a document in the source bucket with any DATA as we only look at.\n<pre class=\"font:monospace font-size:18 line-height:24 toolbar-overlay:false toolbar-hide:false toolbar-delay:false striped:false marking:false ranges:false nums:false nums-toggle:false lang:default decode:true\">KEY spawn_50k_timers::1<\/pre>\n<\/li>\n<li>Inspect the logs after a minute or two.<\/li>\n<li>Delete the document with key &#8220;spawn_50k_timers::1&#8221;.<\/li>\n<li>Inspect the logs after a minute or two.<\/li>\n<li>Undeploy this function.<\/li>\n<\/ul>\n<p>To see the 50K Eventing Timers being created and firing (instead of being canceled):<\/p>\n<ul>\n<li>Edit the function change delayMinutes to 1 (you do not want to wait 4 days).<\/li>\n<li>Deploy the modified function (code below).<\/li>\n<li>Create a document in the source bucket with any DATA as we only look at the KEY.\n<pre class=\"font:monospace font-size:18 line-height:24 toolbar-overlay:false striped:false marking:false ranges:false nums:false nums-toggle:false lang:default decode:true\">KEY spawn_50k_timers::1<\/pre>\n<\/li>\n<li>Inspect the logs after two minutes.<\/li>\n<li>Delete the document with key &#8220;spawn_50k_timers::1&#8221;.<\/li>\n<li>Inspect the logs after a minute or two.<\/li>\n<li>Undeploy this function.<\/li>\n<\/ul>\n<pre class=\"toolbar-overlay:false lang:js decode:true \">function TimerCallback(context) {\r\n    if (context.timer_num == 1 || context.timer_num == 50000)\r\n        log('TimerCallback: fired timer #', context.timer_num);\r\n    \/*\r\n    * take some actions ...\r\n    *\/\r\n}\r\n\r\nfunction OnUpdate(doc, meta) {\r\n    if (meta.id != 'spawn_50k_timers::1') return;\r\n    \r\n    \/\/ Create a timestamp 96 hours from now (4 days)\r\n    var delayMinutes = 60*96;\r\n    var futureTime = new Date(); \r\n    futureTime.setMinutes(futureTime.getMinutes() + delayMinutes);\r\n\r\n    \/\/ make 50K timers \r\n    for (var i=1; i&lt;= 50000; i++) {\r\n        var timer_id = \"tmr_\" + i;\r\n        if (i == 1 || i == 50000)\r\n            log('OnUpdate: create timer # ', i, timer_id);\r\n        try {\r\n            createTimer(TimerCallback, futureTime, timer_id, \r\n                { \"docId\": meta.id, \"timer_num\": i});\r\n        } catch (e) {\r\n            log('OnUpdate:  create #', i, \" error \", e);\r\n        }            \r\n    }\r\n}\r\n\r\nfunction OnDelete(meta, options) {\r\n    if (meta.id != 'spawn_50k_timers::1') return;\r\n    \/*\r\n    * Remove the 50K timer as there is no related control document anymore.\r\n    *\r\n    * Note on a cancel or overwrite there will be documents which will be \r\n    * cleaned up at a) initial firing schedule of the Timers, b) undeployment \r\n    * of the function, or c) a lazy cleaning process by the Eventing Service.\r\n    *\/\r\n    for (var i=1; i&lt;= 50000; i++) {\r\n        var timer_id = \"tmr_\" + i;\r\n        if (i == 1 || i == 50000)\r\n            log('OnDelete: clear timer # ', i, timer_id);\r\n        try {\r\n            cancelTimer(TimerCallback, timer_id);\r\n        } catch (e) {\r\n            log('OnDelete: clear timer #', i, \" error \", e);\r\n        }\r\n    }\r\n}<\/pre>\n<h3>Eventing Statistics are now co-located with Lifecycle Controls<\/h3>\n<p>Four (4) key Eventing statistics in the UI are now co-located with each Functions Lifecycle control. These enhancements simplify the effort and code and diagnose Eventing Functions to quickly make robust business logic.<\/p>\n<p>The developer or administrator can immediately determine that a Function is misbehaving without having to navigate away from the Function&#8217;s lifecycle controls.<\/p>\n<h4>Example:<\/h4>\n<ul>\n<li>Create a &#8220;source&#8221; bucket and a &#8220;metadata&#8221; bucket for Eventing.<\/li>\n<li>Make a few document any KEY and any DATA in the source bucket.<\/li>\n<li>Deploy the modified function (code below) it contains a syntax error,\u00a0 forgetting to put var in front of a variable.<\/li>\n<\/ul>\n<pre class=\"toolbar-overlay:false lang:js decode:true\">function OnUpdate(doc, meta) {\r\n    log('docId', meta.id);\r\n    \/\/ this is an error missing 'var'\r\n    a = 2;\r\n}<\/pre>\n<ul>\n<li>When the Eventing Function is deployed there is an immediate feedback that something went wrong to a developer.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9086\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/08\/evt_66_stats_bad_function1.png\" alt=\"\" width=\"889\" height=\"153\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function1.png 889w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function1-300x52.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function1-768x132.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function1-20x3.png 20w\" sizes=\"auto, (max-width: 889px) 100vw, 889px\" \/><\/p>\n<ul>\n<li>The user responds to the feed back, i.e. &#8220;red&#8221; failures and can inspect the Function for the source of the error.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-9087\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/08\/evt_66_stats_bad_function2.png\" alt=\"\" width=\"893\" height=\"214\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function2.png 918w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function2-300x72.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function2-768x184.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function2-20x5.png 20w\" sizes=\"auto, (max-width: 893px) 100vw, 893px\" \/><\/p>\n<ul>\n<li>Undeploy this Eventing Function.<\/li>\n<li>Fix the error in this case make line 4: &#8220;var a=2;&#8221;.<\/li>\n<li>Deploy this Eventing Function again.<\/li>\n<li>Once the code is fixed the developer can see the correct behavior and progress as success counter now increments.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-9088\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/08\/evt_66_stats_bad_function3.png\" alt=\"\" width=\"890\" height=\"149\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function3.png 890w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function3-300x50.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function3-768x129.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/evt_66_stats_bad_function3-20x3.png 20w\" sizes=\"auto, (max-width: 890px) 100vw, 890px\" \/><\/p>\n<h3>OnDelete Handler now indicates Deletion or Expiration<\/h3>\n<p>The OnDelete Handler now indicates if a document was deleted or expired via a new parameter \u201coptions\u201d.\u00a0 This often requested capability allows different logic to be executed depending on the type of removal.<\/p>\n<h4>Example:<\/h4>\n<ul>\n<li>Create a &#8220;source&#8221; bucket and a &#8220;metadata&#8221; bucket for Eventing<\/li>\n<li>Deploy this function (code below)<\/li>\n<li>Create a document in the source bucket with any DATA as we only look at the KEY\n<pre class=\"font:monospace font-size:18 line-height:24 toolbar-overlay:false striped:false marking:false ranges:false nums:false nums-toggle:false lang:default decode:true \">KEY doc_to_delete::1<\/pre>\n<\/li>\n<li>Inspect the logs after a few seconds<\/li>\n<li>Delete the document with key &#8220;doc_to_delete::1&#8221;<\/li>\n<li>Inspect the logs after a minute<\/li>\n<li>Undeploy this function<\/li>\n<\/ul>\n<pre class=\"toolbar-overlay:false lang:js decode:true \">function OnDelete(meta, options) {\r\n    if (options.expired) {\r\n        log(\"doc expired:\",meta.id);\r\n        \/*\r\n        * take some action ...\r\n        *\/\r\n    } else {\r\n        log(\"doc deleted:\",meta.id);\r\n        \/*\r\n        * take some other action ...\r\n        *\/\r\n    }\r\n}<\/pre>\n<h3>Explore Couchbase Server 6.6 resources<\/h3>\n<table>\n<tbody>\n<tr>\n<td><b>Blogs<\/b><\/td>\n<td><b>Docs and Tutorials<\/b><\/td>\n<td><b>Webpages and Webinars<\/b><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/www.couchbase.com\/blog\/whats-new-and-improved-in-couchbase-server-6-6\/\"><span style=\"font-weight: 400\">What\u2019s New in Couchbase Server 6.6<\/span><\/a><\/td>\n<td><a href=\"https:\/\/docs.couchbase.com\/server\/current\/introduction\/whats-new.html\"><span style=\"font-weight: 400\">What\u2019s New in Couchbase Server 6.6?<\/span><\/a><\/td>\n<td><a href=\"https:\/\/event.on24.com\/eventRegistration\/EventLobbyServlet?target=reg20.jsp&amp;partnerref=website&amp;eventid=2566405&amp;sessionid=1&amp;key=9DB74CF2A4251458E10D64B86B68C0EF&amp;regTag=&amp;sourcepage=register\"><span style=\"font-weight: 400\">New Features in Couchbase Server 6.6: Analytics, Backup, Query, and More<\/span><\/a><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/\"><span style=\"font-weight: 400\">Eventing Improvements (Timers, Handlers, and Statistics)<\/span><\/a><\/td>\n<td><a href=\"https:\/\/docs.couchbase.com\/server\/6.6\/release-notes\/relnotes.html\"><span style=\"font-weight: 400\">Couchbase Server 6.6 Release Notes<\/span><\/a><\/td>\n<td><a href=\"https:\/\/www.couchbase.com\/products\/analytics\/\"><span style=\"font-weight: 400\">Couchbase Analytics Service<\/span><\/a><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/www.couchbase.com\/blog\/remote-links-analyze-your-enterprise-with-couchbase-analytics\/\"><span style=\"font-weight: 400\">Remote Links \u2013 Analyze Your Enterprise With Couchbase Analytics<\/span><\/a><\/td>\n<td><a href=\"https:\/\/index-advisor.couchbase.com\/indexadvisor\/#1\"><span style=\"font-weight: 400\">Try the Couchbase Index Advisor Service<\/span><\/a><\/td>\n<td><a href=\"https:\/\/www.couchbase.com\/products\/server\/whats-new\/\"><span style=\"font-weight: 400\">What\u2019s New in Couchbase Server (Product Page)<\/span><\/a><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/www.couchbase.com\/blog\/external-datasets-extend-your-reach-with-couchbase-analytics\/\"><span style=\"font-weight: 400\">External Datasets \u2013 Extend Your Reach With Couchbase Analytics<\/span><\/a><\/td>\n<td><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/rest-links.html\"><span style=\"font-weight: 400\">Set Up Analytics Remote and S3 Links Using REST API<\/span><\/a><\/td>\n<td><a href=\"https:\/\/www.couchbase.com\/products\/editions\/\"><span style=\"font-weight: 400\">Compare Editions<\/span><\/a><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/www.couchbase.com\/blog\/announcing-flex-index-with-couchbase\/\"><span style=\"font-weight: 400\">Announcing Flex Index With Couchbase<\/span><\/a><\/td>\n<td><a href=\"https:\/\/docs.couchbase.com\/server\/current\/analytics\/5_ddl.html\"><span style=\"font-weight: 400\">Create External Datasets Using Data Definition Language (DDL)<\/span><\/a><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/www.couchbase.com\/blog\/introducing-backing-up-to-object-store-s3\/\"><span style=\"font-weight: 400\">Introducing Backing Up to Object Store (S3)<\/span><\/a><\/td>\n<td><a href=\"https:\/\/docs.couchbase.com\/server\/current\/cli\/cbcli\/couchbase-cli-analytics-link-setup.html\"><span style=\"font-weight: 400\">Set Up Analytics Remote and S3 Links Using CLI<\/span><\/a><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<td><a href=\"https:\/\/www.couchbase.com\/blog\/import-documents-with-admin-ui\/\"><span style=\"font-weight: 400\">Import Documents With the Web Admin Console<\/span><\/a><\/td>\n<td><\/td>\n<td><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>References<\/h3>\n<ul>\n<li>Couchbase Eventing documentation:<br \/>\n<a href=\"https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-overview.html\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-overview.html<\/a><\/li>\n<li>Couchbase Eventing examples:<br \/>\n<a href=\"https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-examples.html\">https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-examples.html<\/a><\/li>\n<li>Couchbase Server 6.6 What&#8217;s New:<br \/>\n<a href=\"https:\/\/docs.couchbase.com\/server\/6.6\/introduction\/whats-new.html\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/docs.couchbase.com\/server\/6.6\/introduction\/whats-new.html<\/a><\/li>\n<li>Couchbase blogs on Eventing:<br \/>\n<a href=\"https:\/\/www.couchbase.com\/blog\/tag\/eventing\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/www.couchbase.com\/blog\/tag\/eventing\/<\/a><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">We would love to hear from you on how you liked the 6.6 features and how it\u2019ll benefit your business going forward. Please share your feedback via the comments or in the Couchbase <\/span><a href=\"https:\/\/www.couchbase.com\/forums\/\"><span style=\"font-weight: 400\">forum<\/span><\/a><span style=\"font-weight: 400\">.\u00a0<\/span><\/p>\n<h3>Footnotes<\/h3>\n<div style=\"font-size: 75%\">\n<p><a id=\"#footnote_1\"><\/a><a href=\"#footnote_1_src\"><sup>[1]<\/sup><\/a> The severity is governed by: a) The number of vBuckets holding an active timer. Therefore if there are only a few timers in the future the issue may not be noticeable or materialize. and b) Whether an Eventing timer has fired recently on a vBucket (which clears the issue for the given vBucket on a per function basis). Therefore 6.5 systems with lots of near term timer activity will not experience this issue even if timers are scheduled far into the future.\u00a0 This is not an issue in 6.6.<\/p>\n<p><a id=\"#footnote_2\"><\/a><a href=\"#footnote_2_src\"><sup>[2]<\/sup><\/a> On a cancelTimer() operation or overwriting an existing Timer by reference there will be a temporary documents in the Eventing &#8220;metadata&#8221; bucket which will be cleaned up at a) at the initial firing schedule of the canceled (or overwritten) Timers, or b) an undeployment of the function. This behavior is unlike a Timer firing at the scheduled time in which all associated Eventing metadata is immediately cleaned up form the\u00a0 Eventing &#8220;metadata&#8221; bucket upon a Timer firing.<\/p>\n<p>&nbsp;<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>With the release of Couchbase 6.6 the Eventing Service has major improvements in functionality. We\u2019ve introduced new Eventing Timers that can be cancelled using the cancelTimer() function, or by creating a new timer with the same reference identifier as an [&hellip;]<\/p>\n","protected":false},"author":42711,"featured_media":11847,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1816,2273,9417],"tags":[],"ppma_author":[9113],"class_list":["post-9083","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-couchbase-server","category-eventing","category-performance"],"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>Eventing Improvements: Timers, Handlers and Statistics - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"New 6.6 Eventing features: Timers can be cancelled or overwritten or used for recurring schedules, ability to differntiate delete v. expiry, and statistics in the UI are co-located with each Functions controls.\" \/>\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\/eventing-improvements-timers-handlers-and-statistics\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Eventing Improvements: Timers, Handlers and Statistics\" \/>\n<meta property=\"og:description\" content=\"New 6.6 Eventing features: Timers can be cancelled or overwritten or used for recurring schedules, ability to differntiate delete v. expiry, and statistics in the UI are co-located with each Functions controls.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-08-12T15:39:57+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T05:39:26+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"1570\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jon Strabala, Principal Product Manager, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jon Strabala, Principal Product Manager, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/\"},\"author\":{\"name\":\"Jon Strabala, Principal Product Manager, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c991579f88217edee79ffedb6fc914cc\"},\"headline\":\"Eventing Improvements: Timers, Handlers and Statistics\",\"datePublished\":\"2020-08-12T15:39:57+00:00\",\"dateModified\":\"2025-06-14T05:39:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/\"},\"wordCount\":1486,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg\",\"articleSection\":[\"Couchbase Server\",\"Eventing\",\"High Performance\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/\",\"name\":\"Eventing Improvements: Timers, Handlers and Statistics - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg\",\"datePublished\":\"2020-08-12T15:39:57+00:00\",\"dateModified\":\"2025-06-14T05:39:26+00:00\",\"description\":\"New 6.6 Eventing features: Timers can be cancelled or overwritten or used for recurring schedules, ability to differntiate delete v. expiry, and statistics in the UI are co-located with each Functions controls.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg\",\"width\":1570,\"height\":628},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Eventing Improvements: Timers, Handlers and Statistics\"}]},{\"@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\/c991579f88217edee79ffedb6fc914cc\",\"name\":\"Jon Strabala, Principal Product Manager, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9c6045b0c2f7b07b0ee10f94ad748a25\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/db52a9f6d84faba430dd38106cdbc16ff02c2066b103b5f6b4cfcde40e83c683?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/db52a9f6d84faba430dd38106cdbc16ff02c2066b103b5f6b4cfcde40e83c683?s=96&d=mm&r=g\",\"caption\":\"Jon Strabala, Principal Product Manager, Couchbase\"},\"description\":\"Jon Strabala is a Principal Product Manager, responsible for the Couchbase Eventing Service. Before joining Couchbase, he spent more than 20 years building software products across various domains, starting with EDA in aerospace then transitioning to building enterprise software focused on what today is coined \u201cIoT\u201d and \u201cat-scale data.\u201d Jon worked for several small software consultancies until eventually starting and managing his own firm. He has extensive experience in NoSQL\/NewSQL, both in contributing and commercializing new technologies such as compressed bitmaps and column stores. Jon holds a bachelor\u2019s degree in electrical engineering and a master's in computer engineering, both from the University of Southern California, and an MBA from the University of California at Irvine.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/jon-strabala\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Eventing Improvements: Timers, Handlers and Statistics - The Couchbase Blog","description":"New 6.6 Eventing features: Timers can be cancelled or overwritten or used for recurring schedules, ability to differntiate delete v. expiry, and statistics in the UI are co-located with each Functions controls.","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\/eventing-improvements-timers-handlers-and-statistics\/","og_locale":"en_US","og_type":"article","og_title":"Eventing Improvements: Timers, Handlers and Statistics","og_description":"New 6.6 Eventing features: Timers can be cancelled or overwritten or used for recurring schedules, ability to differntiate delete v. expiry, and statistics in the UI are co-located with each Functions controls.","og_url":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/","og_site_name":"The Couchbase Blog","article_published_time":"2020-08-12T15:39:57+00:00","article_modified_time":"2025-06-14T05:39:26+00:00","og_image":[{"width":1570,"height":628,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg","type":"image\/jpeg"}],"author":"Jon Strabala, Principal Product Manager, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Jon Strabala, Principal Product Manager, Couchbase","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/"},"author":{"name":"Jon Strabala, Principal Product Manager, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c991579f88217edee79ffedb6fc914cc"},"headline":"Eventing Improvements: Timers, Handlers and Statistics","datePublished":"2020-08-12T15:39:57+00:00","dateModified":"2025-06-14T05:39:26+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/"},"wordCount":1486,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg","articleSection":["Couchbase Server","Eventing","High Performance"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/","url":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/","name":"Eventing Improvements: Timers, Handlers and Statistics - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg","datePublished":"2020-08-12T15:39:57+00:00","dateModified":"2025-06-14T05:39:26+00:00","description":"New 6.6 Eventing features: Timers can be cancelled or overwritten or used for recurring schedules, ability to differntiate delete v. expiry, and statistics in the UI are co-located with each Functions controls.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/08\/couchbase-eventing-performance.jpeg","width":1570,"height":628},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/eventing-improvements-timers-handlers-and-statistics\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Eventing Improvements: Timers, Handlers and Statistics"}]},{"@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\/c991579f88217edee79ffedb6fc914cc","name":"Jon Strabala, Principal Product Manager, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/9c6045b0c2f7b07b0ee10f94ad748a25","url":"https:\/\/secure.gravatar.com\/avatar\/db52a9f6d84faba430dd38106cdbc16ff02c2066b103b5f6b4cfcde40e83c683?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/db52a9f6d84faba430dd38106cdbc16ff02c2066b103b5f6b4cfcde40e83c683?s=96&d=mm&r=g","caption":"Jon Strabala, Principal Product Manager, Couchbase"},"description":"Jon Strabala is a Principal Product Manager, responsible for the Couchbase Eventing Service. Before joining Couchbase, he spent more than 20 years building software products across various domains, starting with EDA in aerospace then transitioning to building enterprise software focused on what today is coined \u201cIoT\u201d and \u201cat-scale data.\u201d Jon worked for several small software consultancies until eventually starting and managing his own firm. He has extensive experience in NoSQL\/NewSQL, both in contributing and commercializing new technologies such as compressed bitmaps and column stores. Jon holds a bachelor\u2019s degree in electrical engineering and a master's in computer engineering, both from the University of Southern California, and an MBA from the University of California at Irvine.","url":"https:\/\/www.couchbase.com\/blog\/author\/jon-strabala\/"}]}},"authors":[{"term_id":9113,"user_id":42711,"is_guest":0,"slug":"jon-strabala","display_name":"Jon Strabala, Principal Product Manager, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/db52a9f6d84faba430dd38106cdbc16ff02c2066b103b5f6b4cfcde40e83c683?s=96&d=mm&r=g","author_category":"","last_name":"Strabala, Principal Product Manager, Couchbase","first_name":"Jon","job_title":"","user_url":"","description":"Jon Strabala is a Principal Product Manager, responsible for the Couchbase Eventing Service. Before joining Couchbase, he spent more than 20 years building software products across various domains, starting with EDA in aerospace then transitioning to building enterprise software focused on what today is coined \u201cIoT\u201d and \u201cat-scale data.\u201d Jon worked for several small software consultancies until eventually starting and managing his own firm. He has extensive experience in NoSQL\/NewSQL, both in contributing and commercializing new technologies such as compressed bitmaps and column stores. Jon holds a bachelor\u2019s degree in electrical engineering and a master's in computer engineering, both from the University of Southern California, and an MBA from the University of California at Irvine."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/9083","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\/42711"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=9083"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/9083\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/11847"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=9083"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=9083"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=9083"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=9083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}