Back

Blog details

AIOZ Storage Rate Limit: Working Within 100 Requests/s

AIOZ Network
7 min readOctober 16, 2026
aioz-storage

The AIOZ Storage rate limit is 100 requests per second, and one line on the Usage Limit page is all AIOZ publishes about it. The docs do not say what the limit is measured against, which calls count toward it, or what a rejected request looks like. Below I mark what is documented and what is not, work out what 100 requests per second means for a real upload job, and show two client-side measures that do not depend on the unknown parts: boto3 retries, and a small limiter I tested locally.

TL;DR:

  • AIOZ Storage's documented defaults are 100 buckets per account, 100 sub-users per account, and a rate limit of 100 requests per second.
  • The docs do not say whether the request limit is per account, key, bucket or IP address, which calls count, or what a request over the limit returns.
  • Because the over-limit response is undocumented, do not rely on retries alone. Cap your own rate below 100 and leave room for retries.
  • boto3 defaults to legacy retry mode with 5 attempts. It retries HTTP 429, 500, 502, 503, 504 and 509. standard mode retries SlowDown and 500, 502, 503 and 504, but not 429, so switching modes can lose coverage.

What Is the AIOZ Storage Rate Limit?

AIOZ Storage's Usage Limit page lists three defaults: 100 buckets per account, 100 sub-users per account, and a rate limit of 100 requests per second. The page gives one reason for them, a uniform quality of service across all customers on AIOZ Storage.

A two-column card: the three limits the AIOZ Storage docs state, and five of the details about the request limit that the docs do not state

What the Docs Say, and What They Leave Out

The documented part is short. Two of the three bullets say "per account". The third, the request limit, has no scope attached. I searched the full AIOZ Storage docs set (all 46 pages in llms-full.txt) and found no other mention of the rate limit, so these details are unknown:

  • What the 100 requests per second is measured against: your account, an access key, a bucket, or an IP address.
  • Which calls count, for example whether listing and each part of a multipart upload count the same as a plain upload.
  • How the second is measured, and whether short bursts above 100 are tolerated.
  • What a request over the limit returns: the HTTP status, the error code, and whether a Retry-After header is sent.
  • Whether sub-users share the account's limit.
  • How to change the default. The page says "by default" and describes no process for changing the values.

What 100 Requests per Second Means in Practice

If every object is one request and the limit applies to your whole account, 10,000 small uploads take at least 100 seconds, and 1,000,000 take at least 10,000 seconds, about 2 hours and 47 minutes. Adding threads does not shorten that. It only gets you to the cap faster.

AWS documents a different shape. Amazon S3 can achieve at least 3,500 PUT, COPY, POST or DELETE requests, or 5,500 GET or HEAD requests, per second per partitioned prefix, scales gradually, and may return 503 (Slow Down) errors while it scales. AWS's figure is per prefix and grows. AIOZ's is a single number with its scope unstated, so size your jobs against 100 until AIOZ says more. If you control how files are laid out, fewer, larger objects mean fewer requests. Splitting a big file with multipart upload goes the other way, because each part is a separate upload call. AIOZ does not say whether parts count toward the limit the same way as whole-object uploads.

Step 1: Know What boto3 Retries Before You Change It

By default a boto3 client uses legacy retry mode with 5 attempts, counting the first request. The boto3 guide lists what each mode retries, and the two lists differ in a way that matters here:

legacy (default)standard
Default attempts5, including the first request3, including the first request
HTTP status codes retried429, 500, 502, 503, 504, 509500, 502, 503, 504
Throttling error codes retriedThrottling, ThrottlingException, ThrottledException, RequestThrottledException, ProvisionedThroughputExceededExceptionThose, plus TooManyRequestsException, RequestLimitExceeded, BandwidthLimitExceeded, LimitExceededException, RequestThrottled, SlowDown and others
BackoffExponential, base factor 2Exponential, base factor 2, capped at 20 seconds

So standard is not a strict upgrade. It recognizes SlowDown, which is what Amazon S3 sends, but it drops 429 and 509 from the status list. If AIOZ answers an over-limit request with a bare HTTP 429 and an error code botocore does not know, legacy retries it and standard may not. If AIOZ sends SlowDown or a 503, standard retries it, and legacy retries the 503 only. I cannot tell you which case applies, because AIOZ does not document the response.

Set the mode and attempt count on purpose, and keep it simple:

import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    region_name="us-east-1",
    aws_access_key_id="YOUR_ACCESS_KEY_ID",
    aws_secret_access_key="YOUR_SECRET_ACCESS_KEY",
    endpoint_url="AIOZ_STORAGE_ENDPOINT_URL",
    config=Config(
        retries={"mode": "legacy", "total_max_attempts": 5},
        request_checksum_calculation="when_required",
        response_checksum_validation="when_required",
        s3={"addressing_style": "path"},
    ),
)

The two when_required settings are there because AIOZ Storage needs a Content-Length header on uploads. Since 1.36.0, boto3 otherwise sends uploads chunked without one (see AWS's data integrity settings and the botocore Config reference). Path-style URLs are required too, because bucket subdomains don't resolve. We confirmed both on Oct 19, 2026; a full upload with real keys is not tested yet.

The region and path-style addressing follow AIOZ's own Python SDK example. total_max_attempts includes the first request, while max_attempts in a Config object counts retries only, so the two names are not interchangeable. Swap "legacy" for "standard" only after your logs (see below) show a code that standard handles and legacy does not. The adaptive mode adds client-side rate limiting, but the boto3 guide calls it experimental and subject to change.

Step 2: Stay Under the Limit With a Client-Side Limiter

Retries react after a request is rejected. A limiter stops you from sending too many in the first place, and it works whatever AIOZ returns. This one allows at most rate calls in any rolling second and is safe to share between threads:

import threading
import time
from collections import deque


class RateLimiter:
    """Allow at most `rate` calls in any rolling one-second window."""

    def __init__(self, rate):
        self.rate = rate
        self.calls = deque()
        self.lock = threading.Lock()

    def wait(self):
        while True:
            with self.lock:
                now = time.monotonic()
                while self.calls and now - self.calls[0] >= 1.0:
                    self.calls.popleft()
                if len(self.calls) < self.rate:
                    self.calls.append(now)
                    return
                pause = 1.0 - (now - self.calls[0])
            time.sleep(pause)


limiter = RateLimiter(80)


def upload(key):
    limiter.wait()
    s3.put_object(Bucket="YOUR_BUCKET_NAME", Key=key, Body=b"example")

Call upload from a ThreadPoolExecutor and the limiter spaces the calls out. I chose 80 as a margin, not because AIOZ says so. Two things make a margin necessary. The limiter cannot see boto3's own retries, and every retry is another request on top of your count. And there is a gap between admitting a call and the request reaching the network.

I tested the limiter with 400 no-op calls at a limit of 80 per second. Measured on the limiter's own admission times, the busiest rolling second held exactly 80 calls with 1, 8 and 32 threads. Measured from timestamps taken by the callers afterwards, the 32-thread run once showed 81, which is that scheduling gap. This was a local test, not a test against AIOZ.

If You Write Your Own Retry Loop

When you retry yourself, add jitter. Marc Brooker's post on the AWS Architecture Blog (4 March 2015) shows that plain exponential backoff still leaves clusters of calls, and that adding random jitter to the sleep spreads them out. He calls jittered backoff "a standard approach for remote clients". If boto3's built-in retries already cover the errors you see, you do not need your own loop. For comparison, AIOZ Stream documents its limits and response headers in Handling API Rate Limits in Production.

Log What You Actually See

Since the response to an over-limit request is undocumented, record it when it happens. Do not try to overload the service on purpose. Just log any throttling-like failure you meet:

from botocore.exceptions import ClientError

try:
    s3.put_object(Bucket="YOUR_BUCKET_NAME", Key="a.txt", Body=b"data")
except ClientError as error:
    meta = error.response["ResponseMetadata"]
    retry_after = meta.get("HTTPHeaders", {}).get("retry-after")
    print(meta["HTTPStatusCode"], error.response["Error"]["Code"], retry_after)

If you see a consistent status, error code or Retry-After value, send it to AIOZ and ask for it to be documented. That answer tells you which retry mode, if either, covers it.

Frequently Asked Questions

What is the AIOZ Storage rate limit?
The Usage Limit page states a default rate limit of 100 requests per second, alongside 100 buckets and 100 sub-users per account.

Is the 100 requests per second limit per account?
The docs do not say. The bucket and sub-user limits are stated per account, but the request limit has no scope attached.

What error does AIOZ Storage return when I exceed the limit?
It is not documented. Log the HTTP status, the error code and any Retry-After header you see, and do not assume a 503 or a 429.

Does boto3 retry throttled requests automatically?
Yes, in both modes, but for different signals. The default legacy mode retries HTTP 429, 500, 502, 503, 504 and 509. standard retries SlowDown and other throttling codes plus 500, 502, 503 and 504. Whether either covers AIOZ's over-limit response is unknown.

Can I raise the limit?
The docs say the values are set by default and describe no way to change them. Ask AIOZ if your workload needs more.

How long does it take to upload a million small files?
At least 10,000 seconds, about 2 hours and 47 minutes, if each file is one request and the limit covers your whole account.

References

We only send updates when meaningful changes ship, and you can unsubscribe anytime

Related Content

blog thumbnail

How to Create a Bucket and Upload a File on AIOZ Storage

Create a bucket and upload a file on AIOZ Storage in five steps: sign up, set a passphrase, add credits, and upload. Plus what the passphrase cannot recover.

aioz-storage
5 min readOctober 20, 2026
blog thumbnail

AIOZ Storage Rate Limit: Working Within 100 Requests/s

The AIOZ Storage rate limit is 100 requests per second. See what the docs do and don't say, and how to stay under it with boto3 retries and a limiter.

aioz-storage
7 min readOctober 16, 2026
blog thumbnail

What AIOZ Storage Erasure Coding Covers and What It Doesn't

AIOZ Storage erasure coding splits each object into pieces on DePIN nodes, so it survives node loss. See what it covers, what it doesn't, and what to back up.

aioz-storage
6 min readOctober 14, 2026
blog thumbnail

How to Rename a File in an S3 Bucket on AIOZ Storage

Rename a file in an S3 bucket on AIOZ Storage from the dashboard, then move, delete and download files, and see which actions the docs say are not supported.

aioz-storage
5 min readOctober 13, 2026
blog thumbnail

AIOZ Storage llms.txt: Docs Built for Super Intelligence

AIOZ Storage publishes llms.txt, a 46-link docs index, and llms-full.txt, all docs in one 164 KB file. See what each file contains and when to use which.

aioz-storage
6 min readOctober 09, 2026
blog thumbnail

Vector Database vs Agent Memory on AIOZ Storage: A Guide

Vector database vs agent memory on AIOZ Storage: use the vector database for control over embeddings and metadata, Memory for simple Record and Recall calls.

aioz-storage
6 min readOctober 06, 2026