{"record":{"id":"c467e1e1719e3de4","repo":"pinpoint-apm/pinpoint","slug":"max-concurrent-requests-reached-table-tablename","errorCode":null,"errorMessage":"max concurrent requests reached. table:<tableName>","messagePattern":"max concurrent requests reached\\. table:<tableName>","errorType":"exception","errorClass":"RequestNotPermittedException","httpStatus":null,"severity":"warning","filePath":"commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/async/RateLimiterPutWriter.java","lineNumber":64,"sourceCode":"        try {\n            final List<CompletableFuture<Void>> results = this.putWriter.put(tableName, puts);\n            if (results != null) {\n                for (CompletableFuture<Void> result : results) {\n                    result.whenComplete(release);\n                }\n                success = true;\n            }\n            return results;\n        } finally {\n            if (!success) {\n                this.limiter.release(size);\n            }\n        }\n    }\n\n    private void acquire(int size, TableName tableName) {\n        if (!this.limiter.acquire(size)) {\n            throw new RequestNotPermittedException(\"max concurrent requests reached. table:\" + tableName, false);\n        }\n    }\n\n    @Override\n    public String toString() {\n        return \"RateLimiterPutWriter{\" +\n                \"putWriter=\" + putWriter +\n                \", limiter=\" + limiter +\n                '}';\n    }\n}\n","sourceCodeStart":46,"sourceCodeEnd":76,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/async/RateLimiterPutWriter.java#L46-L76","documentation":"RateLimiterPutWriter.acquire throws RequestNotPermittedException when the configured rate limiter cannot grant the requested number of permits for the put batch. It back-pressures writers so HBase write traffic stays under the configured request-per-second cap.","triggerScenarios":"Calling put (directly or via put(List)) when limiter.acquire(size) returns false because outstanding permits for the table already reach the configured max; large batch puts consume permits faster than the limiter replenishes.","commonSituations":"Burst write storms from collectors, oversized batch sizes relative to a low hbase.client.put-rate-limit setting, multiple collector instances sharing undersized limits.","solutions":["Raise the rate limiter configuration (permits per period) for the affected table","Reduce put batch size or smooth the producer's write rate","Catch RequestNotPermittedException at the caller and retry with backoff or queue the writes","Verify multiple writers aren't each consuming the limit unexpectedly"],"exampleFix":"// before\nputWriter.put(tableName, mutations); // throws on burst\n// after\nif (acquirePermits(batchSize)) { putWriter.put(tableName, mutations); } else { enqueueForRetry(mutations); }","handlingStrategy":"try-catch","validationCode":"// Query/config check before bulk writes\nint maxPermits = rateLimiterConfig.getPermitsPerPeriod(tableName);\nif (mutations.size() > maxPermits) {\n    logger.warn(\"Batch size {} exceeds rate limit {} for {}\", mutations.size(), maxPermits, tableName);\n}","typeGuard":null,"tryCatchPattern":"try {\n    putWriter.put(tableName, mutations);\n} catch (RequestNotPermittedException e) {\n    logger.warn(\"Rate limited on {}, backing off: {}\", tableName, e.getMessage());\n    retryQueue.offer(mutations); // or backoff+retry\n}","preventionTips":["Size rate-limit config to your actual write throughput including bursts","Break large mutation lists into smaller batches","Add retry-with-backoff around put calls in collectors","Monitor rate-limit rejections per table"],"tags":["hbase","rate-limit","backpressure","async"],"backgroundTag":"rate-limit-exceeded","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}