{"id":13600645,"url":"https://github.com/sethvargo/go-limiter","last_synced_at":"2025-05-13T22:05:01.034Z","repository":{"id":39091800,"uuid":"278512944","full_name":"sethvargo/go-limiter","owner":"sethvargo","description":"A supersonic rate limiting package for Go with HTTP middleware.","archived":false,"fork":false,"pushed_at":"2025-04-12T14:44:37.000Z","size":89,"stargazers_count":625,"open_issues_count":0,"forks_count":47,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-29T21:39:23.748Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sethvargo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-07-10T01:52:04.000Z","updated_at":"2025-04-26T10:41:13.000Z","dependencies_parsed_at":"2024-01-14T04:45:12.177Z","dependency_job_id":"18b51b71-ae43-43f7-ac9f-df817266cba4","html_url":"https://github.com/sethvargo/go-limiter","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvargo%2Fgo-limiter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvargo%2Fgo-limiter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvargo%2Fgo-limiter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sethvargo%2Fgo-limiter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sethvargo","download_url":"https://codeload.github.com/sethvargo/go-limiter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254036817,"owners_count":22003653,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T18:00:45.695Z","updated_at":"2025-05-13T22:05:01.018Z","avatar_url":"https://github.com/sethvargo.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Go Rate Limiter\n\n[![GoDoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/sethvargo/go-limiter)\n[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/sethvargo/go-limiter/test.yml?style=flat-square)](https://github.com/sethvargo/go-limiter/actions/workflows/test.yml)\n\n\nThis package provides a rate limiter in Go (Golang), suitable for use in HTTP\nservers and distributed workloads. It's specifically designed for\nconfigurability and flexibility without compromising throughput.\n\n\n## Usage\n\n1.  Create a store. This example uses an in-memory store:\n\n    ```golang\n    store, err := memorystore.New(\u0026memorystore.Config{\n      // Number of tokens allowed per interval.\n      Tokens: 15,\n\n      // Interval until tokens reset.\n      Interval: time.Minute,\n    })\n    if err != nil {\n      log.Fatal(err)\n    }\n    ```\n\n1.  Determine the limit by calling `Take()` on the store:\n\n    ```golang\n    ctx := context.Background()\n\n    // key is the unique value upon which you want to rate limit, like an IP or\n    // MAC address.\n    key := \"127.0.0.1\"\n    tokens, remaining, reset, ok, err := store.Take(ctx, key)\n\n    // tokens is the configured tokens (15 in this example).\n    _ = tokens\n\n    // remaining is the number of tokens remaining (14 now).\n    _ = remaining\n\n    // reset is the unix nanoseconds at which the tokens will replenish.\n    _ = reset\n\n    // ok indicates whether the take was successful. If the key is over the\n    // configured limit, ok will be false.\n    _ = ok\n\n    // Here's a more realistic example:\n    if !ok {\n      return fmt.Errorf(\"rate limited: retry at %v\", reset)\n    }\n    ```\n\nThere's also HTTP middleware via the `httplimit` package. After creating a\nstore, wrap Go's standard HTTP handler:\n\n```golang\nmiddleware, err := httplimit.NewMiddleware(store, httplimit.IPKeyFunc())\nif err != nil {\n  log.Fatal(err)\n}\n\nmux1 := http.NewServeMux()\nmux1.Handle(\"/\", middleware.Handle(doWork)) // doWork is your original handler\n```\n\nThe middleware automatically set the following headers, conforming to the latest\nRFCs:\n\n- `X-RateLimit-Limit` - configured rate limit (constant).\n- `X-RateLimit-Remaining` - number of remaining tokens in current interval.\n- `X-RateLimit-Reset` - UTC time when the limit resets.\n- `Retry-After` - Time at which to retry\n\n\n## Why _another_ Go rate limiter?\n\nI really wanted to learn more about the topic and possibly implementations. The\nexisting packages in the Go ecosystem either lacked flexibility or traded\nflexibility for performance. I wanted to write a package that was highly\nextensible while still offering the highest levels of performance.\n\n\n### Speed and performance\n\nHow fast is it? You can run the benchmarks yourself, but here's a few sample\nbenchmarks with 100,000 unique keys. I added commas to the output for clarity,\nbut you can run the benchmarks via `make benchmarks`:\n\n```text\n$ make benchmarks\nBenchmarkSethVargoMemory/memory/serial-7      13,706,899      81.7 ns/op       16 B/op     1 allocs/op\nBenchmarkSethVargoMemory/memory/parallel-7     7,900,639       151 ns/op       61 B/op     3 allocs/op\nBenchmarkSethVargoMemory/sweep/serial-7       19,601,592      58.3 ns/op        0 B/op     0 allocs/op\nBenchmarkSethVargoMemory/sweep/parallel-7     21,042,513      55.2 ns/op        0 B/op     0 allocs/op\nBenchmarkThrottled/memory/serial-7             6,503,260       176 ns/op        0 B/op     0 allocs/op\nBenchmarkThrottled/memory/parallel-7           3,936,655       297 ns/op        0 B/op     0 allocs/op\nBenchmarkThrottled/sweep/serial-7              6,901,432       171 ns/op        0 B/op     0 allocs/op\nBenchmarkThrottled/sweep/parallel-7            5,948,437       202 ns/op        0 B/op     0 allocs/op\nBenchmarkTollbooth/memory/serial-7             3,064,309       368 ns/op        0 B/op     0 allocs/op\nBenchmarkTollbooth/memory/parallel-7           2,658,014       448 ns/op        0 B/op     0 allocs/op\nBenchmarkTollbooth/sweep/serial-7              2,769,937       430 ns/op      192 B/op     3 allocs/op\nBenchmarkTollbooth/sweep/parallel-7            2,216,211       546 ns/op      192 B/op     3 allocs/op\nBenchmarkUber/memory/serial-7                 13,795,612      94.2 ns/op        0 B/op     0 allocs/op\nBenchmarkUber/memory/parallel-7                7,503,214       159 ns/op        0 B/op     0 allocs/op\nBenchmarkUlule/memory/serial-7                 2,964,438       405 ns/op       24 B/op     2 allocs/op\nBenchmarkUlule/memory/parallel-7               2,441,778       469 ns/op       24 B/op     2 allocs/op\n```\n\nThere's likely still optimizations to be had, pull requests are welcome!\n\n\n### Ecosystem\n\nMany of the existing packages in the ecosystem take dependencies on other\npackages. I'm an advocate of very thin libraries, and I don't think a rate\nlimiter should be pulling external packages. That's why **go-limit uses only the\nGo standard library**.\n\n\n### Flexible and extensible\n\nMost of the existing rate limiting libraries make a strong assumption that rate\nlimiting is only for HTTP services. Baked in that assumption are more\nassumptions like rate limiting by \"IP address\" or are limited to a resolution of\n\"per second\". While go-limit supports rate limiting at the HTTP layer, it can\nalso be used to rate limit literally anything. It rate limits on a user-defined\narbitrary string key.\n\n\n### Stores\n\n#### Memory\n\nMemory is the fastest store, but only works on a single container/virtual\nmachine since there's no way to share the state.\n[Learn more](https://pkg.go.dev/github.com/sethvargo/go-limiter/memorystore).\n\n#### Redis\n\nRedis uses Redis + Lua as a shared pool, but comes at a performance cost.\n[Learn more](https://pkg.go.dev/github.com/sethvargo/go-redisstore).\n\n#### Noop\n\nNoop does no rate limiting, but still implements the interface - useful for\ntesting and local development.\n[Learn more](https://pkg.go.dev/github.com/sethvargo/go-limiter/noopstore).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsethvargo%2Fgo-limiter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsethvargo%2Fgo-limiter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsethvargo%2Fgo-limiter/lists"}