• Stars
    star
    526
  • Rank 84,247 (Top 2 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A supersonic rate limiting package for Go with HTTP middleware.

Go Rate Limiter

GoDoc GitHub Actions

This package provides a rate limiter in Go (Golang), suitable for use in HTTP servers and distributed workloads. It's specifically designed for configurability and flexibility without compromising throughput.

Usage

  1. Create a store. This example uses an in-memory store:

    store, err := memorystore.New(&memorystore.Config{
      // Number of tokens allowed per interval.
      Tokens: 15,
    
      // Interval until tokens reset.
      Interval: time.Minute,
    })
    if err != nil {
      log.Fatal(err)
    }
  2. Determine the limit by calling Take() on the store:

    ctx := context.Background()
    
    // key is the unique value upon which you want to rate limit, like an IP or
    // MAC address.
    key := "127.0.0.1"
    tokens, remaining, reset, ok, err := store.Take(ctx, key)
    
    // tokens is the configured tokens (15 in this example).
    _ = tokens
    
    // remaining is the number of tokens remaining (14 now).
    _ = remaining
    
    // reset is the unix nanoseconds at which the tokens will replenish.
    _ = reset
    
    // ok indicates whether the take was successful. If the key is over the
    // configured limit, ok will be false.
    _ = ok
    
    // Here's a more realistic example:
    if !ok {
      return fmt.Errorf("rate limited: retry at %v", reset)
    }

There's also HTTP middleware via the httplimit package. After creating a store, wrap Go's standard HTTP handler:

middleware, err := httplimit.NewMiddleware(store, httplimit.IPKeyFunc())
if err != nil {
  log.Fatal(err)
}

mux1 := http.NewServeMux()
mux1.Handle("/", middleware.Handle(doWork)) // doWork is your original handler

The middleware automatically set the following headers, conforming to the latest RFCs:

  • X-RateLimit-Limit - configured rate limit (constant).
  • X-RateLimit-Remaining - number of remaining tokens in current interval.
  • X-RateLimit-Reset - UTC time when the limit resets.
  • Retry-After - Time at which to retry

Why another Go rate limiter?

I really wanted to learn more about the topic and possibly implementations. The existing packages in the Go ecosystem either lacked flexibility or traded flexibility for performance. I wanted to write a package that was highly extensible while still offering the highest levels of performance.

Speed and performance

How fast is it? You can run the benchmarks yourself, but here's a few sample benchmarks with 100,000 unique keys. I added commas to the output for clarity, but you can run the benchmarks via make benchmarks:

$ make benchmarks
BenchmarkSethVargoMemory/memory/serial-7      13,706,899      81.7 ns/op       16 B/op     1 allocs/op
BenchmarkSethVargoMemory/memory/parallel-7     7,900,639       151 ns/op       61 B/op     3 allocs/op
BenchmarkSethVargoMemory/sweep/serial-7       19,601,592      58.3 ns/op        0 B/op     0 allocs/op
BenchmarkSethVargoMemory/sweep/parallel-7     21,042,513      55.2 ns/op        0 B/op     0 allocs/op
BenchmarkThrottled/memory/serial-7             6,503,260       176 ns/op        0 B/op     0 allocs/op
BenchmarkThrottled/memory/parallel-7           3,936,655       297 ns/op        0 B/op     0 allocs/op
BenchmarkThrottled/sweep/serial-7              6,901,432       171 ns/op        0 B/op     0 allocs/op
BenchmarkThrottled/sweep/parallel-7            5,948,437       202 ns/op        0 B/op     0 allocs/op
BenchmarkTollbooth/memory/serial-7             3,064,309       368 ns/op        0 B/op     0 allocs/op
BenchmarkTollbooth/memory/parallel-7           2,658,014       448 ns/op        0 B/op     0 allocs/op
BenchmarkTollbooth/sweep/serial-7              2,769,937       430 ns/op      192 B/op     3 allocs/op
BenchmarkTollbooth/sweep/parallel-7            2,216,211       546 ns/op      192 B/op     3 allocs/op
BenchmarkUber/memory/serial-7                 13,795,612      94.2 ns/op        0 B/op     0 allocs/op
BenchmarkUber/memory/parallel-7                7,503,214       159 ns/op        0 B/op     0 allocs/op
BenchmarkUlule/memory/serial-7                 2,964,438       405 ns/op       24 B/op     2 allocs/op
BenchmarkUlule/memory/parallel-7               2,441,778       469 ns/op       24 B/op     2 allocs/op

There's likely still optimizations to be had, pull requests are welcome!

Ecosystem

Many of the existing packages in the ecosystem take dependencies on other packages. I'm an advocate of very thin libraries, and I don't think a rate limiter should be pulling external packages. That's why go-limit uses only the Go standard library.

Flexible and extensible

Most of the existing rate limiting libraries make a strong assumption that rate limiting is only for HTTP services. Baked in that assumption are more assumptions like rate limiting by "IP address" or are limited to a resolution of "per second". While go-limit supports rate limiting at the HTTP layer, it can also be used to rate limit literally anything. It rate limits on a user-defined arbitrary string key.

Stores

Memory

Memory is the fastest store, but only works on a single container/virtual machine since there's no way to share the state. Learn more.

Redis

Redis uses Redis + Lua as a shared pool, but comes at a performance cost. Learn more.

Noop

Noop does no rate limiting, but still implements the interface - useful for testing and local development. Learn more.

More Repositories

1

go-envconfig

A Go library for parsing struct tags from environment variables.
Go
1,037
star
2

ratchet

A tool for securing CI/CD workflows with version pinning.
Go
771
star
3

go-password

A Golang library for generating high-entropy random passwords similar to 1Password or LastPass.
Go
642
star
4

go-retry

Go library for retrying with configurable backoffs
Go
631
star
5

vault-on-gke

Run @HashiCorp Vault on Google Kubernetes Engine (GKE) with Terraform
HCL
497
star
6

go-githubactions

Go SDK for GitHub Actions - easily author GitHub Actions in Go
Go
434
star
7

vault-secrets-gen

A Vault secrets plugin for generating high entropy passwords and passphrases.
Go
338
star
8

go-signalcontext

Create Go contexts that cancel on signals.
Go
260
star
9

bootstrap_forms

Bootstrap Forms makes Twitter's Bootstrap on Rails easy!
Ruby
253
star
10

vault-kubernetes-authenticator

An app and container for authenticating services to @HashiCorp Vault's via the Kubernetes auth method
Go
205
star
11

powify

Powify is an easy-to-use wrapper for 37 signal's pow
Ruby
189
star
12

vault-kubernetes-workshop

Steps and scripts for running @HashiCorp Vault on @GoogleCloudPlatform Kubernetes
Shell
154
star
13

chef-sugar

143
star
14

terraform-provider-googlecalendar

A @HashiCorp Terraform provider for managing Google Calendar events.
Go
136
star
15

go-diceware

Golang library for generating passphrases via the diceware algorithm.
Go
99
star
16

secrets-in-serverless

A collection of examples for doing secrets management in serverless lambda or cloud functions.
Go
91
star
17

vault-init

Automate the initialization and unsealing of @HashiCorp Vault on @GoogleCloudPlatform
Go
82
star
18

atlantis-on-gke

A set of @HashiCorp Terraform configurations for running Atlantis on @GoogleCloud GKE
HCL
68
star
19

vault-token-helper-osx-keychain

An example @HashiCorp Vault token helper for Mac OS X Keychain.
Go
65
star
20

vault-demo

Walkthroughs and scripts for my @HashiCorp Vault talks
Shell
65
star
21

terraform-provider-filesystem

A @HashiCorp Terraform provider for interacting with the filesystem
Go
62
star
22

hashicorp-installer

Script and Docker container for installing @HashiCorp tools
Shell
50
star
23

vault-auth-slack

A @HashiCorp Vault plugin for authenticating and receiving policies via Slack.
Go
50
star
24

cleanroom

(More) safely evaluate Ruby DSLs with cleanroom
Ruby
44
star
25

go-cache

Cache implementations in Go, with support for generics.
Go
44
star
26

cloud-run-docker-mirror

Mirror images from one Docker repository to another, as a service.
Go
38
star
27

vault-puppet

Using @HashiCorp Vault with Puppet
Shell
36
star
28

gcs-cacher

Utility for saving and restoring caches backed by Google Cloud Storage.
Go
35
star
29

base64-is-not-encryption

Demo repo showing Kubernetes secrets being sad
Shell
31
star
30

fast

A CLI tool for testing download speed using Netflix's fast.com service.
Go
27
star
31

isbndb

Ruby ISBNdb is a simple, Ruby library that connects to ISBNdb.com's Web Service and API.
Ruby
26
star
32

go-redisstore

Go rate limiter interface for Redis
Go
18
star
33

terraform-provider-berglas

A Terraform provider for Berglas
Go
17
star
34

vault-fluentd-configurations

Fluentd configurations for @HashiCorp Vault
17
star
35

go-gcpkms

Wrappers around Google Cloud KMS that implement Go's crypto.Signer and crypto.Verifier interfaces.
Go
16
star
36

now-or-never-resource-optimizer

A resource optimizer for Now or Never, written in Go, compiled to WASM, run in the browser.
Go
16
star
37

go-gcslock

A Go library for acquiring a forward-looking lock in Google Cloud Storage.
Go
14
star
38

terraform-cloud-run-demo

Sample Terraform configurations for creating a publicly accessible Cloud Run service
HCL
13
star
39

vault-token-helper-gcp-kms

A @HashiCorp Vault token helper for encrypting/decrypting via @GoogleCloudPlatform KMS
Go
12
star
40

kubecon18

Scripts and demo for my Kubecon 2018 talk
HCL
10
star
41

go-malice

A malicious package to demonstrate the importance of software supply chain security.
Go
7
star
42

zapw

Finds common errors for the zap logger using static analysis.
Go
7
star
43

powify.dev

The official web-management tool for Powify
Ruby
7
star
44

envjector

Exec a subprocess with an environment specified in a file. Like env, but a single static binary across multiple operating systems.
Go
6
star
45

go-hello-githubactions

Sample code for GitHub Actions with Go
Dockerfile
5
star
46

gcpkms-rand

Use Google Cloud KMS as an io.Reader and rand.Source.
Go
5
star
47

serverless-secrets-talk

Demo script and code for secrets in serverless talk.
Go
4
star
48

envserver

A webserver that prints the environment it was spawned in
Go
3
star
49

community-zero

3
star
50

spellingbee

A small Go program to generate solutions to the NYT Spelling Bee.
Go
2
star
51

cloud-run-empathy-sms-hello-world

Sample code for sending text messages via Twilio on Cloud Run.
Python
2
star
52

go-redisstore-opencensus

Go rate limiter interface for Redis with instrumentation.
Go
2
star
53

chatty

Go
1
star
54

terraform-secret-manager-demo

HCL
1
star
55

terraform-0.13-google-cloud-demo

Sample for Terraform 0.13 unique features on Google Cloud
HCL
1
star
56

docker-postgres-pgaudit

A Docker image for postgres with pgAudit available
Makefile
1
star