





{"id":434115,"date":"2020-10-23T14:22:52","date_gmt":"2020-10-23T14:22:52","guid":{"rendered":"https:\/\/exotel.com\/uae\/?post_type=blog&#038;p=434115"},"modified":"2023-12-01T11:26:22","modified_gmt":"2023-12-01T11:26:22","slug":"building-a-browser-push-notification-service-using-golang","status":"publish","type":"blog","link":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/","title":{"rendered":"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang"},"content":{"rendered":"<!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD HTML 4.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/REC-html40\/loose.dtd\">\n<html><body><p><em>(This article originally appeared as a part of a 3 part series <a href=\"https:\/\/medium.com\/swlh\/building-a-browser-push-notification-service-the-low-level-design-using-the-gorilla-websocket-aa8372f3e113\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.)<\/em><\/p>\n<p>At Exotel, we have a lot of customers running their support and sales call centers on us. When these agents receive calls, having a real-time notification, with contextual information about the details of the caller, on their browser, saves the customers and the agents a lot of time. It provides for a better customer experience since they do not have to go into the details of any on-going support queries or problems. To make this happen, we have a Push Notification Service that ensures real-time delivery of these notifications.<\/p>\n<p><span style=\"font-weight: 400;\"><br>\nGenerally, building a reliable push notification service (using the WebSocket protocol) comes with its own set of challenges. This article will talk about the design and implementation details to help overcome these.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\"><br>\nThe Pledge<\/span><\/h2>\n<p><span style=\"font-weight: 400;\"><br>\nWe will look at the low-level design of the WebSocket server (that handles the push notifications). It leverages the <a href=\"https:\/\/github.com\/gorilla\/websocket\" target=\"_blank\" rel=\"noopener noreferrer\">gorilla\/WebSocket<\/a> library. We&rsquo;ll rely immensely on two essential resources provided by the go language &mdash; the <strong>go-routines<\/strong> and the <strong>go-channels<\/strong>.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>What are go-routines and go-channels, you ask?<\/strong> Well, the go language is known to have greatly eased the work of having a multithreaded architecture, both for the developer and also from the resource utilization angle (memory and CPU usage). It has provided two things to help this cause, the <strong><a href=\"https:\/\/golangbot.com\/goroutines\/\" target=\"_blank\" rel=\"noopener noreferrer\">go-routines<\/a><\/strong>, which are the methods that can run concurrently with other methods, basically given a fancy name and a makeover. These can be thought of very lightweight threads (~2kb). And the <strong>go-channels<\/strong>, which are the communication wires between these go-routines.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\"><strong>So essentially, if you want to run something concurrently?<\/strong> Simply create a new go-routine (which is super cheap and easy).<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>Now, you want to communicate between these go-routines?<\/strong> [no_highlight background_color=&rdquo;#E0DFDF&rdquo; color=&rdquo;#000000&Prime;]Avoid sharing the memory or the variables between these routines, you&rsquo;ll probably end up frustrated, trying to resolve issues that come with concurrency (race conditions etc.).[\/no_highlight] Instead, pass this variable over something like the communication wire, to the intended go-routines, and this communication wire is <strong>go-channels<\/strong> (in-built in go), which passes all the tests of concurrency. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is inline with the language&rsquo;s philosophy that says &ldquo;Don&rsquo;t communicate by sharing the memory, share the memory by communicating&rdquo;. The channels are like having a queue to communicate between two services, just that this one&rsquo;s going to reside in your memory, and will help you to communicate between your threads.<\/span><\/p>\n<h2><span style=\"font-weight: 400;\"><br>\nThe Turn<\/span><\/h2>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>Okay, got the terms, now how does the low-level design look like?<\/strong> Well, it would look something like this.<\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-368198 size-large\" src=\"https:\/\/exotel.com\/wp-content\/uploads\/sites\/4\/2020\/10\/browser-push-notification-service-golang.jpeg\" alt=\"\" width=\"1024\" height=\"509\"><\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400;\"><strong>The go-routines and the channels<\/strong> &mdash; Here in this architecture, the different boxes denote the different types of worker pools that will run in our server.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\nThe worker pools are basically like the different departments in a company. Like how the department employs an employee to get the job done, each worker pool may employ 1 or more workers (go-routines) to get the job done.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\nThese company departments need to constantly communicate with each other to achieve a larger company objective. Likewise, the arrows between these workers denote the communication wires laid out for the workers to talk to each other (or the go-channels), which collectively achieve the objective of delivering the notification to our targets. The pool of workers will try to make some requests to some other pool to take care of the next part of the processing, and these requests will be sent over the channels.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\nLet us have a look at the different types of worker pools and their jobs.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>1. Source (connection upgrade request) worker pool (HTTP server) &ndash;<\/strong>&nbsp;This worker pool processes the incoming connection upgrade requests. It will look at the targetID, the request fields, and the headers, and decide if the request is worthy of a WebSocket upgrade (based on the origin of the request, the authentication credentials, etc.). It will accordingly approve or reject the request.<br>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Rejecting the request would simply mean passing back a non OK status as an HTTP response.<br>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">While approving the request would mean three things<br>\n<\/span><\/p>\n<ul>\n<li><span style=\"font-weight: 400;\"><strong>Sending an HTTP OK status<\/strong> in the response.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>Forwarding the connection object to the &lsquo;Hub pool&rsquo; of workers<\/strong>, this is what we will call a registration request to the hub. More on this in the Hub pool section.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>Starting two go-routines<\/strong> (a read pump go-routine and a write-pump go-routine), for handling the reads and writes for this connection. More on this in the read pump \/ write pump worker pool section.<br>\n<\/span><\/li>\n<\/ul>\n<p><strong>The &lsquo;source (connection upgrade request) worker pool&rsquo; can have any number of go-routines running based on the incoming connection-upgrade-requests traffic.<\/strong><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>For our case in point, the person Alexander sent a connection upgrade request tagged with the target &lsquo;Alexander&rsquo; as soon as he opened our website on any of the devices. This worker then forwarded these connection registration requests to the hub pool. It would also start a read pump and a write pump, against each one of these connection requests.<\/strong><\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>2. Source (notification request) worker pool (HTTP \/ GRPC or Queue worker) &ndash;<\/strong>&nbsp;This worker pool sources the notification requests. These requests will be tagged with the targetID (the intended receiver). This pool will simply forward all the valid notification requests to the &lsquo;Hub pool&rsquo; for further processing.<br>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>The &lsquo;source (notification request) pool&rsquo; can have any number of go-routines based on the incoming notifications-traffic.<\/strong><br>\n<\/span><\/p>\n<p><strong>For our case in point, this worker received a notification &lsquo;Hello, Alexander Hamilton!&rsquo; tagged against the target &lsquo;Alexander&rsquo;. This worker then forwarded the notification request to the hub pool.<\/strong><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>3. The Hub pool &ndash;<\/strong>&nbsp;This worker pool, as you might have seen is the most critical component in the architecture. This stores all the current active connections (active connections meaning, a connection that has been upgraded to a websocket and has not been closed yet) in a map[targetID]connections. All the notifications are to be sent over this connection object. The hub takes care of three things.<\/span><\/p>\n<ol>\n<li><span style=\"font-weight: 400;\">For a connection <strong>registration<\/strong> request, store the new connection in the map against the given targetID.<\/span><\/li>\n<li>For a connection <strong>deregistration<\/strong> request, remove the connection from the map. (Who sends this, you ask? Well, it may originate mostly from the read pump or the write pump. More on this in the relevant sections.) Additionally, this will also send a close-go-routine-request to the read and the write pump go-routines that run for this connection.<\/li>\n<li>For a <strong>notification<\/strong> request, it will search the map and get the active connections stored against that targetID, and forward the request to all the write pumps running for those connections. If it does not have any active connection against the targetID, it can simply discard the notification.<\/li>\n<\/ol>\n<p><span style=\"font-weight: 400;\"><br>\nSo, overall, if you see, this pool takes care of any and all read \/ write operations on the map.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>Unfortunately, the Hub pool will only have a single worker go-routine., since the map in golang does not support concurrent operations inherently.<\/strong><\/span><\/p>\n<p><strong><br>\nFor the case in point, the connection registration requests would end up populating the connections in the map, as [Alexander]three-connections. Additionally, when the notification request comes to this hub, it would figure that there are three connections against the target &lsquo;Alexander&rsquo; and would forward the request to all of these three connections&rsquo; write pumps.<\/strong><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>4. The Read pump &ndash; <\/strong>This go-routine will be created one per connection immediately after the connection upgrade request is approved. This routine will continuously keep polling over the connection object, to check if there&rsquo;s data sent over the connection by the target client (if you remember the earlier <a href=\"https:\/\/medium.com\/@singhania94\/building-a-browser-push-notification-service-http-long-polling-and-the-web-socket-protocol-5e83cd1420c1?source=friends_link&amp;sk=f8b0fdd9acd6fe7eab29fd2d611c2db3\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a>, we&rsquo;d seen that websockets enables a duplex communication). It will then forward the received notification to the appropriate processor. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">Additionally, as soon as this pump gets some error while reading over the connection, this will send a deregistration request for this connection to the hub routine.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>The read pump go-routine, as we&rsquo;ve discussed, runs one per active connection.<\/strong><\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>5. The Write pump &ndash;<\/strong> The write pump will also be created one per connection, which handles the work of last-mile delivery of the notification through the connection. The notifications forwarded by the hub are, in this routine, written to the connection buffer by this pump. Here also, as we&rsquo;d seen in the read-pump, as soon as it gets some error while pushing over the connection, it will send a deregistration request for this connection to the hub routine.<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>The write pump go-routine runs one per active connection.<\/strong><\/span><\/p>\n<p><span style=\"font-weight: 400;\"><br>\n<strong>For our case in point, the write pump against each of the three connections would receive the notification &lsquo;Hello, Alexander Hamilton!&rsquo; and they would simply write this over the connection that they&rsquo;re running for.<\/strong><\/span><\/p>\n<p><span style=\"font-weight: 400;\">Now, we&rsquo;re left with one last piece of the puzzle, ie. communication between these workers. For all of these requests that the workers have to make to each other, channels are extensively used. As in the diagram, the channels used are-<\/span><\/p>\n<ol>\n<li><span style=\"font-weight: 400;\">Hub Connection Registration Request Channel<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Hub Connection Deregistration Request Channel<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Hub Write Notification Channel<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Write Pump Write Notification Channel (1 per connection)<\/span><\/li>\n<li><span style=\"font-weight: 400;\">(optional) Read Pump Received Notification Channel<\/span><\/li>\n<\/ol>\n<h2><span style=\"font-weight: 400;\">The Prestige<\/span><\/h2>\n<p><span style=\"font-weight: 400;\"><br>\nThe WebSocket protocol allowed us to efficiently exploit the hardware resources. That, clubbed with the virtues of go language, helped us build a scalable and efficient push notification service, to provide for a seamless customer experience.<br>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-368198 size-large\" src=\"https:\/\/exotel.com\/wp-content\/uploads\/sites\/4\/2020\/10\/golang-browser-push-notification-2.jpeg\" alt=\"\" width=\"1024\" height=\"509\"><\/span><\/p>\n<p>&nbsp;<\/p>\n<div>Additional Resources<\/div>\n<p>1. How to Create a Support Agent Appreciation Bot Using Hangouts and Exotel in 7 Easy Steps<\/p>\n<p>2. Improving your omnichannel customer experience &ndash; personalised problem solving<\/p>\n<\/body><\/html>\n","protected":false},"excerpt":{"rendered":"<p>(This article originally appeared as a part of a 3 part series here.) At Exotel, we have a lot of customers running their support and sales call centers on us. When these agents receive calls, having a real-time notification, with contextual information about the details of the caller, on their browser, saves the customers and [&hellip;]<\/p>\n","protected":false},"author":18,"featured_media":434116,"template":"","meta":{"_acf_changed":false,"om_disable_all_campaigns":false},"tags":[],"blog-category":[228],"components":[],"class_list":["post-434115","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog-category-technology-and-roadmap"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v27.1.1) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang\" \/>\n<meta property=\"og:description\" content=\"(This article originally appeared as a part of a 3 part series here.) At Exotel, we have a lot of customers running their support and sales call centers on us. When these agents receive calls, having a real-time notification, with contextual information about the details of the caller, on their browser, saves the customers and [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/\" \/>\n<meta property=\"og:site_name\" content=\"UAE\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-01T11:26:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"600\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/gif\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/\",\"url\":\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/\",\"name\":\"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang\",\"isPartOf\":{\"@id\":\"https:\/\/exotel.com\/uae\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif\",\"datePublished\":\"2020-10-23T14:22:52+00:00\",\"dateModified\":\"2023-12-01T11:26:22+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#breadcrumb\"},\"inLanguage\":\"en-AE\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-AE\",\"@id\":\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#primaryimage\",\"url\":\"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif\",\"contentUrl\":\"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif\",\"width\":1200,\"height\":600},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/exotel.com\/uae\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blogs\",\"item\":\"https:\/\/exotel.com\/uae\/en\/blog\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/exotel.com\/uae\/#website\",\"url\":\"https:\/\/exotel.com\/uae\/\",\"name\":\"Exotel\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/exotel.com\/uae\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/exotel.com\/uae\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-AE\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/exotel.com\/uae\/#organization\",\"name\":\"Exotel\",\"url\":\"https:\/\/exotel.com\/uae\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-AE\",\"@id\":\"https:\/\/exotel.com\/uae\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2025\/07\/green-black-logo.png\",\"contentUrl\":\"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2025\/07\/green-black-logo.png\",\"width\":373,\"height\":110,\"caption\":\"Exotel\"},\"image\":{\"@id\":\"https:\/\/exotel.com\/uae\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang","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:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/","og_locale":"en_US","og_type":"article","og_title":"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang","og_description":"(This article originally appeared as a part of a 3 part series here.) At Exotel, we have a lot of customers running their support and sales call centers on us. When these agents receive calls, having a real-time notification, with contextual information about the details of the caller, on their browser, saves the customers and [&hellip;]","og_url":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/","og_site_name":"UAE","article_modified_time":"2023-12-01T11:26:22+00:00","og_image":[{"width":1200,"height":600,"url":"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif","type":"image\/gif"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/","url":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/","name":"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang","isPartOf":{"@id":"https:\/\/exotel.com\/uae\/#website"},"primaryImageOfPage":{"@id":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#primaryimage"},"image":{"@id":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#primaryimage"},"thumbnailUrl":"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif","datePublished":"2020-10-23T14:22:52+00:00","dateModified":"2023-12-01T11:26:22+00:00","breadcrumb":{"@id":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#breadcrumb"},"inLanguage":"en-AE","potentialAction":[{"@type":"ReadAction","target":["https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/"]}]},{"@type":"ImageObject","inLanguage":"en-AE","@id":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#primaryimage","url":"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif","contentUrl":"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2023\/05\/Building-Browser-Push-Notification-Service.gif","width":1200,"height":600},{"@type":"BreadcrumbList","@id":"https:\/\/exotel.com\/uae\/en\/blog\/building-a-browser-push-notification-service-using-golang\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/exotel.com\/uae\/en\/"},{"@type":"ListItem","position":2,"name":"Blogs","item":"https:\/\/exotel.com\/uae\/en\/blog\/"},{"@type":"ListItem","position":3,"name":"Building a Browser Push Notification Service \u2014 The Low-Level Design Using the Gorilla\/Websocket Library in Golang"}]},{"@type":"WebSite","@id":"https:\/\/exotel.com\/uae\/#website","url":"https:\/\/exotel.com\/uae\/","name":"Exotel","description":"","publisher":{"@id":"https:\/\/exotel.com\/uae\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/exotel.com\/uae\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-AE"},{"@type":"Organization","@id":"https:\/\/exotel.com\/uae\/#organization","name":"Exotel","url":"https:\/\/exotel.com\/uae\/","logo":{"@type":"ImageObject","inLanguage":"en-AE","@id":"https:\/\/exotel.com\/uae\/#\/schema\/logo\/image\/","url":"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2025\/07\/green-black-logo.png","contentUrl":"https:\/\/exotel.com\/uae\/wp-content\/uploads\/sites\/4\/2025\/07\/green-black-logo.png","width":373,"height":110,"caption":"Exotel"},"image":{"@id":"https:\/\/exotel.com\/uae\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/blog\/434115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/users\/18"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/media\/434116"}],"wp:attachment":[{"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/media?parent=434115"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/tags?post=434115"},{"taxonomy":"blog-category","embeddable":true,"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/blog-category?post=434115"},{"taxonomy":"components","embeddable":true,"href":"https:\/\/exotel.com\/uae\/en\/wp-json\/wp\/v2\/components?post=434115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}