go-admingo-admin
  • Guide
  • Development
    • Advanced
    • Commands
  • Advanced
  • Help
  • GitHub
  • Changelog
⌘ K
Standard Practice
Standard Module Development
Backend Basics
Backend Directory Structure
Backend Config File
Starting the Backend
Frontend Basics
Frontend Directory Structure
Frontend Config File
Starting the Frontend
Development Patterns
Actions Pattern
Hand-Written Pattern
First API Endpoint
Layered Development
API Layer
Service Layer
DTO Definitions
Model Definitions
Router Registration
Multi-Environment Config
Database Table Conventions
Data Permissions
Response Format
Code Generation
Pre-Generation Setup
Generating Business Code
One-Click Menu Generation
Binding APIs to the Menu
Configuring Role Permissions
Verifying the Feature
Generating Code with an LLM
Advanced Capabilities
Runtime Core API
Authentication & Authorization
Logging
Request Tracing
Cache
Queue
File Upload
Rate Limiting
Scheduled Jobs
Air Hot Reload
Swagger Docs
Code Generation Tool
Last updated:
Open-source MIT Licensed | Copyright © 2020-present
Powered by go-admin-team

TABLE OF CONTENTS

‌
‌
‌
‌

Rate Limiting

go-admin implements a global rate limiter on top of Alibaba's Sentinel, to keep a burst of traffic from taking the service down.

The Current Rule

The limiter is defined in common/middleware/sentinel.go and applied globally, to every route, in cmd/api/server.go:

go
func Sentinel() gin.HandlerFunc {
system.LoadRules([]*system.Rule{
{
MetricType: system.InboundQPS,
TriggerCount: 200,
Strategy: system.BBR,
},
})
return sentinel.SentinelMiddleware(
sentinel.WithBlockFallback(func(ctx *gin.Context) {
ctx.AbortWithStatusJSON(200, map[string]interface{}{
"msg": "too many request; the quota used up!",
"code": 500,
})
}),
)
}

The rule is fixed: once the whole service's inbound QPS goes above 200, Sentinel starts rejecting some requests using an adaptive strategy (BBR) — not a simple "reject everything past the threshold".

The Response When Rate-Limited

A throttled request gets:

json
{
"code": 500,
"msg": "too many request; the quota used up!"
}

WARNING

The HTTP status code is 200, not 429 or 500. A frontend or client that only checks the HTTP status to decide success or failure will read this as a success — it needs to also check the code field in the response body.

This differs from the Response Format used elsewhere: a rate-limited response carries no requestId, since it happens at the Sentinel middleware layer, before the RequestId middleware has populated the context.

Adjusting the Threshold or Turning It Off

Nothing in the config controls this limiter — the threshold and strategy are hardcoded in common/middleware/sentinel.go; adjusting or disabling it means changing the code and rebuilding:

  • Adjust the threshold: change the TriggerCount value;
  • Turn it off: remove the r.Use(common.Sentinel()) line in cmd/api/server.go.

For a single-instance deployment with modest concurrency, 200 QPS is usually never reached. Before load testing or a multi-instance deployment, it's worth evaluating whether this threshold still fits — it's set per process, so the aggregate traffic a multi-instance deployment can absorb scales with the instance count, but each instance still enforces its own 200 QPS on its own.

Known Issue: Possible Crash Under Concurrent Access

ERROR

The pinned sentinel-golang v1.0.4 has a crash under high concurrency, reported by several people in issue #788, still unfixed as of now.

The symptom is the process crashing or flooding the logs once traffic picks up, with the stack pointing into sentinel-golang's internal leap_array.go — a concurrent-access counter issue, not a bug in the application code.

If production hits an unexplained crash under meaningful traffic, disabling the limiter as described above is a reasonable way to rule this out first.

WARNING

Where to get help:

If anything in this guide is unclear, please open an issue.