Caching in Go (Golang): Redis, in-memory and other solutions

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Caching in Go (Golang): Redis, in-memory and other solutions



Caching is one of the key strategies for improving performance and reducing database load in Go applications. In this article, we will cover the main approaches and libraries for implementing caching: from simple in-memory solutions to distributed caching based on Redis. You will learn when to choose which tool and how to properly organize caching in Go projects.



1. Built-in capabilities: map and sync.Map



The simplest way to cache in Go is using a regular map with a mutex or the thread-safe sync.Map. These approaches are suitable for small projects or prototypes where complex invalidation policies are not required.



Example with sync.Map:



package main

import ( "fmt" "sync")

type Cache struct { data sync.Map}

func (c *Cache) Set(key string, value interface{}) { c.data.Store(key, value)}

func (c *Cache) Get(key string) (interface{}, bool) { return c.data.Load(key)}

func main() { cache := &Cache{} cache.Set("user:1", "Alice") if val, ok := cache.Get("user:1"); ok { fmt.Println("Found:", val) }}


Pros: simplicity, zero dependencies.
Cons: no TTL, no automatic cleanup, memory is not limited.



2. In-memory cache with TTL: freecache



Freecache is a fast in-memory cache library with TTL (time-to-live) support. It uses a segmented architecture to minimize locking and efficiently manages memory.



Installation:

go get github.com/coocood/freecache


Usage example:



package main

import ( "fmt" "github.com/coocood/freecache")

func main() { // Create a cache of 100 MB cache := freecache.NewCache(100 * 1024 * 1024)

// Set a value with a TTL of 10 seconds cache.Set([]byte("mykey"), []byte("myvalue"), 10)

// Get the value if val, err := cache.Get([]byte("mykey")); err == nil { fmt.Println("Value:", string(val)) } else { fmt.Println("Key not found or expired") }}


Pros: automatic TTL cleanup, low CPU usage, support for large data volumes.
Cons: single-process only (not distributed).



3. BigCache — an alternative to freecache



BigCache is another popular in-memory library, optimized for storing a large number of entries (millions) with minimal access time. It also supports TTL and automatic eviction of old data.



Example:



package main

import ( "fmt" "github.com/allegro/bigcache/v3" "time")

func main() { config := bigcache.Config{ Shards: 1024, LifeWindow: 10 * time.Minute, CleanWindow: 5 * time.Minute, MaxEntriesInWindow: 1000 * 10 * 60, MaxEntrySize: 500, Verbose: true, }

cache, _ := bigcache.NewBigCache(config) cache.Set("mykey", []byte("bigcache value")) val, _ := cache.Get("mykey") fmt.Println(string(val))}


Pros: high performance with a large number of keys, flexible configuration.
Cons: like freecache — local cache only.



4. Distributed caching with Redis and go-redis



For distributed systems where multiple application instances need a shared cache, Redis is used. The most popular client for Go is go-redis (formerly go-redis/redis).



Installation:

go get github.com/redis/go-redis/v9


Basic caching example:

Recommendations