{"id":24486,"date":"2022-12-01T00:00:00","date_gmt":"2022-12-01T00:00:00","guid":{"rendered":"https:\/\/www.mailgun.com\/blog\/golangs-superior-cache-solution-memcached-redis-2\/"},"modified":"2026-09-16T16:56:38","modified_gmt":"2026-09-16T16:56:38","slug":"golangs-superior-cache-solution-memcached-redis","status":"publish","type":"blog","link":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/","title":{"rendered":"GroupCache: la cach\u00e9 superior de Golang"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Golang cache makes\u202fdistributed caching and synchronization simple and easy\u202fto deploy with GroupCache. But why is this the superior tool? And what problems does it solve? At Mailgun we have used GroupeCache to reduce latency in our rate-limiting service and reaped the benefits of synchronization, while avoiding deadlock issues when creating and managing unique resources. If you\u2019re not convinced, that\u2019s ok, we\u2019re sure you will be by the end of this.<\/p>\n\r\n    <nav data-content-type=\"longform\" class=\"toc-block longform-spacings px-5 py-6 px-md-6 px-lg-7 py-md-7 bg-light fs-sm rounded-lg\" aria-labelledby=\"toc-title-9965\"><p class=\"h5 m-0\" id=\"toc-title-9965\">\u00cdndice<\/p><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">01<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#what-is-a-distributed-cache\">What is a distributed cache?<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">02<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#how-does-distributed-caching-work\">How does distributed caching work?<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">03<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#solving-the-thundering-herd-problem-cache-stampedes-and-high-concurrency\">Solving the thundering herd problem: Cache stampedes and high concurrency<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">04<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#what-is-groupcache-and-how-does-it-compare-to-other-caching-solutions\">What is GroupCache and how does it compare to other caching solutions?<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">05<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#groupcache-as-a-synchronization-tool\">GroupCache as a synchronization tool<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">06<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#using-groupcache\">Using GroupCache<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">07<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#how-to-implement-with-http-2-and-tls\">How to implement with HTTP\/2 and TLS<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">08<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#mailguns-key-removal-update\">Mailgun\u2019s key removal update<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">09<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#mailguns-performance-improvements-using-groupcache\">Mailgun\u2019s performance improvements using GroupCache<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">10<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#conclusion-distributed-caching-made-easy\">Conclusion: Distributed caching made easy<\/a><\/div><\/div><\/nav>\n<h2 class=\"wp-block-heading\">What is a distributed cache?<\/h2>\n\n<p class=\"wp-block-paragraph\">A cache is a high-speed memory storage solution that holds high demand data to speed up data access retrieval. <b>A Distributed cache divides the cache into segments and distributes them<\/b> such that each node in a cluster of servers contains only one segment of the entire cache. In this way, the cache can continue to scale by simply adding new nodes to the cluster.<\/p>\n\n<p class=\"wp-block-paragraph\">This is important for a couple of reasons.<\/p>\n\n<ol class=\"wp-block-list\">\n<li><b>Distributed caches allow the cache to grow as the data grows.<\/b> They are advantageous in environments with high data volume and load.<\/li>\n\n\n\n<li><b>A distributed cache can span multiple servers<\/b> giving it a much higher transaction capacity.<\/li>\n<\/ol>\n\n<h2 class=\"wp-block-heading\">How does distributed caching work?<\/h2>\n\n<p class=\"wp-block-paragraph\">Distributed caching systems like Redis and Memcached clients typically work like this:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>The <b>App<\/b>\u202fasks the <b>Client<\/b> for the cached data via a key.<\/li>\n\n\n\n<li>Then the <b>Client<\/b> performs a consistent hash on the key to determine which <b>Node<\/b> has the data.<\/li>\n\n\n\n<li>Once the <b>Client<\/b> has located the data, it makes a network request to the <b>Node<\/b>.<\/li>\n\n\n\n<li>The <b>Node<\/b> returns the data if found.<\/li>\n\n\n\n<li>The <b>App<\/b> checks if data is returned, else it renders or fetches the data from the database. <\/li>\n\n\n\n<li>The <b>App<\/b> tells <b>Client<\/b> to store data for this key.<\/li>\n\n\n\n<li>The <b>Client<\/b> performs a consistent hash on the key to determine which <b>Node<\/b> should own the data.<\/li>\n\n\n\n<li>Finally, the <b>Client<\/b> stores the data on the <b>Node<\/b>.<\/li>\n<\/ul>\n\n<p class=\"wp-block-paragraph\">Looking at this flow, there are two big implications that stand out: <\/p>\n\n<ol class=\"wp-block-list\">\n<li>Every cache request results in a round trip to a <b>Node<\/b> regardless of cache hit or miss.<\/li>\n\n\n\n<li>You can\u2019t avoid the round trip to a <b>Node<\/b> by caching the value locally, as the remote <b>Node<\/b> could invalidate the data at any time without the <b>Apps<\/b> knowledge.<\/li>\n<\/ol>\n\n<p class=\"wp-block-paragraph\">While neither of these implications are particularly troublesome for most applications, the extra round trips to the database can impact high performance, low latency applications. However, there is one more implication that may not be immediately obvious: the thundering herd!<\/p>\n\n<h2 class=\"wp-block-heading\">Solving the thundering herd problem: Cache stampedes and high concurrency<\/h2>\n\n<p class=\"wp-block-paragraph\"><b>The thundering herd problem is a stampede of requests that overwhelm the system.<\/b> Sometimes called a cache stampede, dogpiling, or the slashdot effect, this problem happens when concurrent instances of an application all attempt to access data at the same time.<\/p>\n\n<p class=\"wp-block-paragraph\">For this discussion, our thundering herd is in response to a cache miss, meaning the data was either removed or never placed in the cache. For example, in normal operation, <b>an application remains responsive under heavy load as long as the data remains cached<\/b>.<\/p>\n\n<p class=\"wp-block-paragraph\">When the cache doesn\u2019t have the data this thundering herd of concurrent work could overwhelm the system and result in congestion, and potential collapse, of the system.<\/p>\n\n<p class=\"wp-block-paragraph\">To combat this concurrent work, you need a system to synchronize fetching or rendering of the data. Fortunately,\u202f<b>there is a Golang library called <\/b><a href=\"https:\/\/github.com\/mailgun\/groupcache\" target=\"_tabs\" rel=\"noopener noreferrer\"><b>GroupCache<\/b><\/a><b> which can be used to resolve the thundering herd issue<\/b>\u202fand improve on the remote cache implications we mentioned.<\/p>\n\n<h2 class=\"wp-block-heading\">What is GroupCache and how does it compare to other caching solutions?<\/h2>\n\n<p class=\"wp-block-paragraph\">There are many caching solutions on the market. Golang\u2019s GroupCache is an open source solution that differs from popular tools like BigCache, Redis and Memcache, as it <b>integrates directly with your code as an In Code Distributed Cache (ICDC)<\/b>. This means that every instance of the <b>App<\/b> <i>is<\/i> a <b>Node<\/b> in the distributed cache. The advantage? As a full member of the distributed cache, each application instance knows the data structures, not only how to store data for the node, but also how to fetch or render the data if it\u2019s missing.<\/p>\n\n<p class=\"wp-block-paragraph\">To understand why this is superior to Redis or Memcached, lets run through the distributed caching flow when using GroupCache. When reading through the flow, keep in mind <b>the\u202fGroupCache\u202fis a library used by the application that also listens for incoming requests from other instances of the application<\/b> that are using\u202fGroupCache.<\/p>\n\n<ol class=\"wp-block-list\">\n<li>The <b>App<\/b> asks the <b>GroupCache<\/b> for the data via a key.<\/li>\n\n\n\n<li>Next, the <b>GroupCache<\/b> checks the in memory hot cache for the data, if no data, continue.<\/li>\n\n\n\n<li>The <b>GroupCache<\/b> performs a consistent hash on the key to determine which <b>GroupCache<\/b> instance has the data.<\/li>\n\n\n\n<li>Then, the <b>GroupCache<\/b> makes a network request to the <b>GroupCache instance<\/b> that has the data.<\/li>\n\n\n\n<li>The <b>GroupCache<\/b> returns the data if it exists in memory, if not it asks the <b>App<\/b> to render or fetch data.<\/li>\n\n\n\n<li>Finally, the <b>GroupCache<\/b> returns the data to <b>GroupCache instance<\/b> that initiated the request. <\/li>\n<\/ol>\n\n<p class=\"wp-block-paragraph\"><b>Step 5<\/b> is significant in the context of a thundering herd event as <b>only one of the GroupCache instances<\/b> will perform the render or fetch of the data requested. All other instances of the application \u2013 that are also requesting the data from the\u202fGroupCache\u202finstance \u2013will block until the owning instance of the application successfully renders or fetches the data. <b>This creates a natural synchronization point for data access in the distributed<\/b> system and negates the thundering herd problem. <\/p>\n\n<p class=\"wp-block-paragraph\"><b>Step 2<\/b> is also significant as the ability to locally cache the data in memory which avoids the cost of a network round trip, providing a huge performance benefit and reduced network pressure. Since <b>GroupCache<\/b> is a part of the application, we avoid the possibility of the <b>GroupCache<\/b> deleting the data without the application\u2019s knowledge, as any such delete event is shared by all instances of the application using <b>GroupCache<\/b>. <\/p>\n\n<p class=\"wp-block-paragraph\">An admittedly minor benefit \u2013 but one that those of us who enjoy simplicity can appreciate \u2013 is that of deployment. Although it is not overly difficult to deploy and secure Redis and Memcached as separate entities from the application, having a single application to deploy means one less thing for an operator to deal with and keep up to date and secure. <\/p>\n\n<p class=\"wp-block-paragraph\">It\u2019s worth mentioning again as it\u2019s easy to overlook. The ability for the cache implementation to render or fetch the data from a database during a cache miss, and the ability to rely on a local in memory hot cache is what makes GroupCache a superior choice among distributed caches. No distributed cache external to your application can provide these benefits.<\/p>\n\n<h2 class=\"wp-block-heading\">GroupCache as a synchronization tool<\/h2>\n\n<p class=\"wp-block-paragraph\">Because GroupCache provides great synchronization semantics, we have found GroupCache to be <b>a superior alternative to distributed or database level locks<\/b> when creating and managing unique resources.<\/p>\n\n<p class=\"wp-block-paragraph\">As an example, our internal analytics engine reads thousands of events and dynamically adds tags with assigned stats. Since we have many instances of the engine running, every new tag seen must be treated as a possible new tag. Normally this would generate a constant stream of upsert requests to our database. By using GroupCache, each instance can query the cache with <code>account:tag<\/code> key.<\/p>\n\n<p class=\"wp-block-paragraph\">If the tag already exists, it\u2019s returned with the latest data on the tag. However, if the tag doesn\u2019t exist, GroupCache relays the request to the owning instance and creates the tag. In this manner, only a single upsert is sent to the database when the system encounters a new tag.<\/p>\n\n<p class=\"wp-block-paragraph\">Similarly, we use GroupCache to count unique counters where the system should only record a single instance of a counter. Because we are using <b>Groupcache,\u202fwe avoid using a distributed lock and deadlock issues completely<\/b>. This is especially useful when using a nosql database with little to no locking or synchronization semantics of their own.<\/p>\n\n<h2 class=\"wp-block-heading\">Using GroupCache<\/h2>\n\n<p class=\"wp-block-paragraph\">Mailgun runs a modified version of <i>Brad Fitzpatrick\u2019s (<\/i><a href=\"https:\/\/github.com\/patrickmn\/go-cache\" target=\"_tabs\" rel=\"noopener noreferrer\"><i>patrickmn<\/i><\/a><i>)<\/i>\u202foriginal <a href=\"https:\/\/github.com\/mailgun\/groupcache\" target=\"_tabs\" rel=\"noopener noreferrer\">GroupCache library on github.com<\/a>.<\/p>\n    <div data-content-type=\"longform\"  class=\"callout text-body-color px-5 py-6 px-md-6 px-lg-7 py-md-7 longform-spacings rounded-lg bg-light\" data-theme=\"light\">\r\n\r\n        <div class=\"content-body\"> For API docs and examples, see <a href='http:\/\/godoc.org\/github.com\/mailgun\/groupcache'>http:\/\/godoc.org\/github.com\/mailgun\/groupcache<\/a><\/div>\r\n    <\/div>\r\n\n<p class=\"wp-block-paragraph\">Notable changes to the library are:<\/p>\n\n<ul class=\"wp-block-list\">\n<li>Support for explicit key removal from a group. <code>Remove()<\/code><\/li>\n\n\n\n<li>Support for expired values. <code>SetBytes()<\/code>, <code>SetProto()<\/code> and <code>SetString()<\/code> now accept an optional <code>time.Time{}<\/code> which represents a time in the future when the value will expire<\/li>\n\n\n\n<li>Support for golang standard <code>context.Context<\/code><\/li>\n\n\n\n<li>Always populates the hotcache<\/li>\n\n\n\n<li>To use GroupCache, you create a Pool of instances each GroupCache instance will talk to, then you create multiple independent cache Groups which use the same Pool of instances.<\/li>\n\n\n\n<li>Keep track of peers in our cluster and add our instance to the pool `<code>http:\/\/localhost:8080` pool := groupcache.NewHTTPPoolOpts(\"http:\/\/localhost:8080\", &amp;groupcache.HTTPPoolOptions{}<\/code>)<\/li>\n\n\n\n<li>Add more peers <code>pool.Set(\"http:\/\/peer1:8080\", \"http:\/\/peer2:8080\")<\/code><\/li>\n\n\n\n<li>Create a new group cache with a max cache size of 3MB group: = <code>groupcache.NewGroup(\"users\", 3000000, groupcache.GetterFunc( func(ctx context.Context, id string, dest groupcache.Sink) error { \/\/ Returns a protobuf struct `User` if user, err := fetchUserFromMongo(ctx, id); err != nil { return err }<\/code><\/li>\n\n\n\n<li>Set the user in the groupcache to expire after 5 minutes <code>if err := dest.SetProto(&amp;user, time.Now().Add(time.Minute*5)); err != nil { return err } return nil }, ))<\/code> <\/li>\n\n\n\n<li>var user User<\/li>\n\n\n\n<li>Fetch the definition from the group cache ctx, <code>cancel := context.WithTimeout(context.Background(), time.Second*10) if err := group.Get(ctx, \u201ckey\u201d, groupcache.ProtoSink(&amp;user)); err != nil { return nil, err } cancel()<\/code> <\/li>\n<\/ul>\n\n<h2 class=\"wp-block-heading\">How to implement with HTTP\/2 and TLS<\/h2>\n\n<p class=\"wp-block-paragraph\">GroupCache uses HTTP to communicate between instances in the cluster. If your application also uses HTTP, GroupCache can use the same HTTP port as your application. Simply add the pool as a handler with it\u2019s own path.<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copia al portapapeles\" data-clipboard-success-label=\"\u00a1Copiado!\" data-clipboard-error-label=\"No se ha podido copiar\" data-tooltip=\"Copia al portapapeles\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copia al portapapeles\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    1\/\/ Our application2http.HandleFunc(&quot;\/&quot;, func(w http.ResponseWriter, r *http.Request) {3 fmt.Fprint(w, &quot;Hi there&quot;)4})5\/\/ Handle GroupCache requests6http.Handle(&quot;\/_groupcache\/&quot;, pool)7log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))8\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<p class=\"wp-block-paragraph\">If your application has TLS configured, GroupCache will benefit from the same TLS config your application uses, additionally having the option of enabling HTTP\/2 which further improves performance of GroupCache requests.\u202f<a href=\"https:\/\/www.mailgun.com\/es\/blog\/dev-life\/ejemplo-cliente-http-2-cleartext-h2c-go\/\" target=\"_tabs\" rel=\"noopener noreferrer\">You can also use HTTP\/2 without TLS via H2C<\/a>.<\/p>\n\n<h2 class=\"wp-block-heading\">Mailgun\u2019s key removal update<\/h2>\n\n<p class=\"wp-block-paragraph\"><b>A notable difference to the Mailgun version of GroupCache is\u202fthe ability to explicitly delete keys from the cache.<\/b> When an instance wants to remove a key, it first deletes the key from the owning instance and then sends the delete requests to all other instances in the pool. This ensures any future requests from non-owner instances in the pool to the owner will result in a new fetch or render of the data (or an error if the data is no longer available.)<\/p>\n\n<p class=\"wp-block-paragraph\">As with any distributed system, there is the possibility that an instance is not available, or connectivity has been lost when the remove request was made. In this scenario <code>group.Remove()<\/code> will return an error indicating that some instances were not contacted and the nature of the error. <\/p>\n\n<p class=\"wp-block-paragraph\">Depending on the use case, the user then has the option of retrying the <code>group.Remove()<\/code> call or ignoring the error. For some systems, ignoring the error might be acceptable especially if you are using the expired values feature. <\/p>\n\n<p class=\"wp-block-paragraph\">The expire values feature allows you to provide an optional expiration time <code>time.Time<\/code> which specifies a future time when the data should expire.<\/p>\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copia al portapapeles\" data-clipboard-success-label=\"\u00a1Copiado!\" data-clipboard-error-label=\"No se ha podido copiar\" data-tooltip=\"Copia al portapapeles\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copia al portapapeles\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    1\/\/ Our application2http.HandleFunc(&quot;\/&quot;, func(w http.ResponseWriter, r *http.Request) {3 fmt.Fprint(w, &quot;Hi there&quot;)4})5\/\/ Handle GroupCache requests6http.Handle(&quot;\/_groupcache\/&quot;, pool)7log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))8\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n<p class=\"wp-block-paragraph\">In the scenario above where we temporarily lose connectivity to an instance, we say that the pool of instances is in an inconsistent state. However, when used in conjunction with the data expiration feature we know the system will eventually become consistent again when the data on the disconnected instances expires. <\/p>\n\n<p class=\"wp-block-paragraph\">There are other much more complex solutions to solving this problem but we have found in practice eventually consistent solutions are <b>the simplest and least error prone way<\/b> to deal with network disruptions.<\/p>\n    <div data-content-type=\"longform\"  class=\"callout text-body-color px-5 py-6 px-md-6 px-lg-7 py-md-7 longform-spacings rounded-lg bg-light\" data-theme=\"light\">\r\n\r\n        <div class=\"content-body\"> A quick note about discovery, while GroupCache doesn\u2019t provide a method of discovering instances there are several widely available systems to make discovery simple. Here\u2019s a few options to get you started:<\/div><ul class=\"mb-0 mt-3\"><li><a href='https:\/\/github.com\/etcd-io\/etcd'>Etcd<\/a><\/li><li><a href='https:\/\/github.com\/kubernetes\/kubernetes'>Kubernetes<\/a><\/li><li><a href='https:\/\/github.com\/hashicorp\/consul'>Consul<\/a><\/li><li><a href='https:\/\/github.com\/hashicorp\/memberlist'>MemberList<\/a><\/li><\/ul>\r\n    <\/div>\r\n\n<h2 class=\"wp-block-heading\">Mailgun\u2019s performance improvements using GroupCache<\/h2>\n\n<p class=\"wp-block-paragraph\">At Mailgun, our first production use of GroupCache was in\u202four ratelimit service. Since this service must operate at a very high performance\/low latency level, traditional caching systems were a concern, the more round trips we introduced to the request pipeline the more opportunities we had to introduce additional latency.<\/p>\n\n<p class=\"wp-block-paragraph\">The following graphs <b>show the total number of cache hits and of those hits the total number of hits that resulted in a roundtrip to another GroupCache instance<\/b>. This demonstrates exactly how much we benefit from the local in memory hot cache as opposed to making a roundtrip call on every request.<\/p>\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4841\" width=\"961\" height=\"469\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-22_at_4.18.53_PM__1_.png\" alt=\"Graph showing GroupCache hits and misses per second\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-22_at_4.18.53_PM__1_.png 961w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-22_at_4.18.53_PM__1_-300x146.png 300w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-22_at_4.18.53_PM__1_-768x375.png 768w\" sizes=\"(max-width: 961px) 100vw, 961px\" \/><\/figure>\n\n<p class=\"wp-block-paragraph\">You can see in the next graph exactly how much MongoDB and our application benefits from the thundering herd avoidance as new keys are retrieved from the system.<\/p>\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" class=\"wp-image-4842\" width=\"696\" height=\"693\" src=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-23_at_12.44.44_PM__2_.png\" alt=\"GroupCache peer request graph\" srcset=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-23_at_12.44.44_PM__2_.png 696w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-23_at_12.44.44_PM__2_-150x150.png 150w, https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/Screen_Shot_2022-11-23_at_12.44.44_PM__2_-300x300.png 300w\" sizes=\"(max-width: 696px) 100vw, 696px\" \/><\/figure>\n\n<p class=\"wp-block-paragraph\">The actual calls to MongoDB are a small fraction of the total requests actually made to the service. This, in addition to the speed of gubernator, is what allows our ratelimit service to perform at low latency even during high load.<\/p>\n\n<p class=\"wp-block-paragraph\">Here you can see the rate limits service response time metrics. Keep in mind for each request we make a gubernator call and a GroupCache request which may or may not result in a GroupCache http request or MongoDB request.\u202f<i>(This graph shows the slowest of the responses, not the average)<\/i>.<\/p>\n\n<h2 class=\"wp-block-heading\">Conclusion: Distributed caching made easy<\/h2>\n\n<p class=\"wp-block-paragraph\">GroupCache has improved performance for our services at Mailgun. It makes <b>distributed caching and synchronization simple and easy<\/b> to deploy. My hope is that others will discover the same benefits that we are enjoying and inspire other ICDC implementations in other languages.<\/p>\n\n<p class=\"wp-block-paragraph\">Was this helpful? At Mailgun we are constantly evaluating and implementing new ways to help scale our services and improve our performance. This isn\u2019t always easy. We\u2019d love for you to learn from our experiences. Subscribe to our newsletter for more content like this.<\/p>\n    <div data-content-type=\"longform\" class=\"longform-spacings\">\r\n        <div class=\"cta bg-primary rounded-lg px-5 py-6 p-md-7 px-md-6\">\r\n                    <div class=\"form-subscription\">\r\n                            <div class=\"h4 mb-3\">\r\n                    Keep me posted! Get great resources in your inbox every week.                <\/div>\r\n                                    <form accept-charset=\"UTF-8\" action=\"\" enctype=\"multipart\/form-data\" data-form-subscription method=\"POST\" style=\"max-width: 400px;\">\r\n                <div class=\"row justify-content-between align-items-top g-2\">\r\n                    <div class=\"col-10\">\r\n                        <input type=\"email\" name=\"email\" class=\"form-control\" placeholder=\"Email\" autocomplete=\"email\" required>\r\n                        <div data-fs=\"error\" role=\"alert\" class=\"invalid-feedback\">\r\n                            Please complete this required field.                        <\/div>\r\n                    <\/div>\r\n                                            <div class=\"col-12 order-last mt-3 fs-xxs\" data-fs=\"acceptance\" style=\"display:none;\">\r\n                            \r\n                                <div class=\"form-check\">\r\n                                    <input id=\"formSubscriptionAcceptance-terms-2419\" class=\"form-check-input\"\r\n                                        type=\"checkbox\" name=\"terms\">\r\n                                    <label for=\"formSubscriptionAcceptance-terms-2419\" class=\"form-check-label text-body-color\">\r\n                                        He le\u00eddo y acepto los T\u00e9rminos de Servicio.                                        <span class=\"hs-form-required\">*<\/span>\r\n                                    <\/label>\r\n                                <\/div>\r\n\r\n                            \r\n                                <div class=\"form-check\">\r\n                                    <input id=\"formSubscriptionAcceptance-privacy-7616\" class=\"form-check-input\"\r\n                                        type=\"checkbox\" name=\"privacy\">\r\n                                    <label for=\"formSubscriptionAcceptance-privacy-7616\" class=\"form-check-label text-body-color\">\r\n                                        He le\u00eddo y acepto la Pol\u00edtica de Privacidad.                                        <span class=\"hs-form-required\">*<\/span>\r\n                                    <\/label>\r\n                                <\/div>\r\n\r\n                                                    <\/div>\r\n                    \r\n                                            <div class=\"col-12 order-last fs-xxs mb-0 mt-2 text-body-color\">\r\n                            Send me the Mailjet Newsletter. I expressly agree to receive the newsletter and know that I can easily unsubscribe at any time.                        <\/div>\r\n                    \r\n                    <div class=\"col-2\">\r\n                        <button type=\"submit\" value=\"Submit\" aria-label=\"Submit\" class=\"btn btn-secondary btn-icon\">\r\n                            <svg aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/layout\/chevron-right.svg\"><\/svg>\r\n                        <\/button>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <input type=\"hidden\" name=\"formSubscriptionRecaptchaToken\" data-fs=\"recaptcha-token\">\r\n                <input type=\"hidden\" name=\"customListID\" value=\"\">\r\n\r\n            <\/form>\r\n            <div data-fs=\"message-success\" style=\"display: none;\">\r\n                <p class=\"mb-0 mt-2 text-body-color\">\r\n                    Check your inbox monthly for your Mailjet Newsletter!                <\/p>\r\n            <\/div>\r\n        <\/div>\r\n        <\/div>\r\n    <\/div>\r\n","protected":false},"excerpt":{"rendered":"<p>La cach\u00e9 de Golang, tambi\u00e9n conocida como GroupCache, ha sido una incorporaci\u00f3n fant\u00e1stica a nuestro conjunto de herramientas de servicios distribuidos en Mailgun. A continuaci\u00f3n te explicamos c\u00f3mo puedes implementarla en el tuyo.<\/p>\n","protected":false},"author":35,"featured_media":4843,"menu_order":0,"template":"","meta":{"_acf_changed":false,"footnotes":""},"blog_category":[23],"class_list":["post-24486","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog_category-it-and-engineering"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>La soluci\u00f3n de cach\u00e9 superior de Golang frente a Memcached y Redis - Transactional Email API Service For Developers | Mailgun<\/title>\n<meta name=\"description\" content=\"GroupCache ha sido una incorporaci\u00f3n fant\u00e1stica a nuestro conjunto de herramientas de servicios distribuidos en Mailgun. A continuaci\u00f3n te explicamos c\u00f3mo puedes implementarla en el tuyo.\" \/>\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.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"La soluci\u00f3n de cach\u00e9 superior de Golang frente a Memcached y Redis - Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"og:description\" content=\"GroupCache ha sido una incorporaci\u00f3n fant\u00e1stica a nuestro conjunto de herramientas de servicios distribuidos en Mailgun. A continuaci\u00f3n te explicamos c\u00f3mo puedes implementarla en el tuyo.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/\" \/>\n<meta property=\"og:site_name\" content=\"Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-16T16:56:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png\" \/>\n\t<meta property=\"og:image:width\" content=\"720\" \/>\n\t<meta property=\"og:image:height\" content=\"448\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\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=\"10 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/\",\"name\":\"La soluci\u00f3n de cach\u00e9 superior de Golang frente a Memcached y Redis - Transactional Email API Service For Developers | Mailgun\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"datePublished\":\"2022-12-01T00:00:00+00:00\",\"dateModified\":\"2026-09-16T16:56:38+00:00\",\"description\":\"GroupCache ha sido una incorporaci\u00f3n fant\u00e1stica a nuestro conjunto de herramientas de servicios distribuidos en Mailgun. A continuaci\u00f3n te explicamos c\u00f3mo puedes implementarla en el tuyo.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"width\":720,\"height\":448},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/it-and-engineering\\\/golangs-superior-cache-solution-memcached-redis\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"GroupCache: la cach\u00e9 superior de Golang\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#website\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"description\":\"Potentes API de email transaccional que te permiten enviar, recibir y hacer seguimiento de emails, creadas pensando en los desarrolladores. \u00a1Descubre m\u00e1s!\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#organization\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"width\":512,\"height\":512,\"caption\":\"Transactional Email API Service For Developers | Mailgun\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/es\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"La soluci\u00f3n de cach\u00e9 superior de Golang frente a Memcached y Redis - Transactional Email API Service For Developers | Mailgun","description":"GroupCache ha sido una incorporaci\u00f3n fant\u00e1stica a nuestro conjunto de herramientas de servicios distribuidos en Mailgun. A continuaci\u00f3n te explicamos c\u00f3mo puedes implementarla en el tuyo.","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.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/","og_locale":"es_ES","og_type":"article","og_title":"La soluci\u00f3n de cach\u00e9 superior de Golang frente a Memcached y Redis - Transactional Email API Service For Developers | Mailgun","og_description":"GroupCache ha sido una incorporaci\u00f3n fant\u00e1stica a nuestro conjunto de herramientas de servicios distribuidos en Mailgun. A continuaci\u00f3n te explicamos c\u00f3mo puedes implementarla en el tuyo.","og_url":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/","og_site_name":"Transactional Email API Service For Developers | Mailgun","article_modified_time":"2026-09-16T16:56:38+00:00","og_image":[{"width":720,"height":448,"url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"10 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/","url":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/","name":"La soluci\u00f3n de cach\u00e9 superior de Golang frente a Memcached y Redis - Transactional Email API Service For Developers | Mailgun","isPartOf":{"@id":"https:\/\/www.mailgun.com\/es\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/#primaryimage"},"image":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","datePublished":"2022-12-01T00:00:00+00:00","dateModified":"2026-09-16T16:56:38+00:00","description":"GroupCache ha sido una incorporaci\u00f3n fant\u00e1stica a nuestro conjunto de herramientas de servicios distribuidos en Mailgun. A continuaci\u00f3n te explicamos c\u00f3mo puedes implementarla en el tuyo.","breadcrumb":{"@id":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/"]}]},{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/#primaryimage","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","width":720,"height":448},{"@type":"BreadcrumbList","@id":"https:\/\/www.mailgun.com\/es\/blog\/it-and-engineering\/golangs-superior-cache-solution-memcached-redis\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.mailgun.com\/es\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/www.mailgun.com\/es\/blog\/"},{"@type":"ListItem","position":3,"name":"GroupCache: la cach\u00e9 superior de Golang"}]},{"@type":"WebSite","@id":"https:\/\/www.mailgun.com\/es\/#website","url":"https:\/\/www.mailgun.com\/es\/","name":"Transactional Email API Service For Developers | Mailgun","description":"Potentes API de email transaccional que te permiten enviar, recibir y hacer seguimiento de emails, creadas pensando en los desarrolladores. \u00a1Descubre m\u00e1s!","publisher":{"@id":"https:\/\/www.mailgun.com\/es\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.mailgun.com\/es\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/www.mailgun.com\/es\/#organization","name":"Transactional Email API Service For Developers | Mailgun","url":"https:\/\/www.mailgun.com\/es\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/www.mailgun.com\/es\/#\/schema\/logo\/image\/","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","width":512,"height":512,"caption":"Transactional Email API Service For Developers | Mailgun"},"image":{"@id":"https:\/\/www.mailgun.com\/es\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/24486","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/users\/35"}],"version-history":[{"count":3,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/24486\/revisions"}],"predecessor-version":[{"id":24678,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog\/24486\/revisions\/24678"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/media\/4843"}],"wp:attachment":[{"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/media?parent=24486"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.mailgun.com\/es\/wp-json\/wp\/v2\/blog_category?post=24486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}