Skip to main content

Squillify development is paused indefinitely. Read why, and discover what this experiment achieved. Read the story

MicroSkills Reference

Rate Limit Simulator

network.rate_limit_check

ProductionBounded custom (Class B)Deterministicstrictfastv1.0.0
No network

Overview

You describe the policy — a fixed window, a sliding window, or a token bucket — and hand us the snapshot you already hold: the request timestamps for a window, or the bucket's tokens and last refill for a bucket. We return whether this request fits, what is left, when the window resets or how long to wait, and for a bucket the state you should store next. Every instant comes from your request and the arithmetic is exact decimal, so the same snapshot always gives the same verdict. This is a simulator for planning and testing: it is not Squillify's own limiter, it reads no live counter, and it reserves or consumes nothing — deciding is yours to do with what we return.

Rate-limit bugs are found in production because testing them means waiting for real windows to roll over, and because every service rounds the edges differently. Making the policy and the instant explicit inputs turns throttling into something you can test at the boundary, compare across languages, and explain to a caller.

Reliability

Fully deterministic: the same snapshot, policy and instant always give the same verdict, because there is no clock and token maths is exact decimal rounded to six places rather than floating point. Window edges are precise: a fixed window is aligned to whole multiples of windowSeconds from the epoch, and a sliding window drops a request exactly windowSeconds old. Failures, none of which are worth retrying unchanged: RATE_POLICY_INVALID means the policy contradicts itself or mixes fields from another type — a bucket field on a window policy, a non-positive capacity or requestCost, or tokens above capacity — so fix the policy and resend. RATE_SNAPSHOT_INCOMPLETE means the type needs data you did not send, such as requestTimestamps for a window or bucketState for a bucket, so send the full snapshot (an empty array is a valid history). RATE_TIMESTAMP_INVALID means an instant is unparseable, has no offset, or is after timestamp, so correct the instant rather than trusting the verdict. RATE_EVENT_LIMIT_EXCEEDED means you sent more than 10000 timestamps, so trim the history to the window you are evaluating. RATE_ARITHMETIC_OVERFLOW means the wait for enough tokens is longer than a millisecond count can report exactly, which needs a refill rate near zero, so raise refillPerSecond.

Context footprint

Returns one small verdict object; the history you send is never echoed back. A successful call costs 1 execution credit.

When to use it

When you hold the counters and want the verdict, the remaining allowance, and the exact wait for one request at one instant.

When you need enforcement on live traffic, when you expect the skill to keep the counters, or when you are checking Squillify's own quota.

Scope

Note
Evaluate one request against a fixed-window, sliding-window, or token-bucket policy using a snapshot the caller supplies.

Non-goals

  • Is not Squillify's own rate limiter and cannot authorize a real request
  • Does not read, reserve, consume, or mutate any live counter
  • Does not store the bucket for you — persist nextState yourself
  • Does not read a clock; the instant comes from your request
  • Does not send or inspect any HTTP traffic

Properties

IdempotentRetry safeStreaming supportedFile input supportedRequires external service

Capabilities

analysisvalidation

Cost & billing

Flat rate per invocation

MetercallsBillable onsuccessCost per call1 credit

File handling

Accepts file_refProduces file_refMax input1 MB

How we handle your data

Sensitive input, safe output
What this means

This skill may receive sensitive content, but it does not target sensitive data and returns only a structured non-sensitive result.

Squillify guarantees
  • Runs inside Squillify
  • This skill runs inside Squillify.
  • Payloads are not sent to an external service by this skill.
  • Squillify does not permanently store submitted payloads.
  • Telemetry records metadata only, not submitted content.
  • Submitted payloads are not used for training.
  • Submitted payloads are not reviewed by humans.
  • This skill does not target sensitive data.
  • The response does not contain submitted content.
Your responsibility

Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.

Read the Microskill Data Handling Policy

Input schema

FieldTypeRequiredDescription
keystringYesSubject identifier of 1 to 256 characters with no control characters; never echoed.
policyobjectYesClosed policy: type plus the fields that type needs. Window types need limit and windowSeconds; TOKEN_BUCKET needs capacity and refillPerSecond.
timestampstringYesISO-8601 instant with offset used as the only now for this evaluation.
requestCostnumberNoHow much this request costs, above 0 and up to 1000000; omit it for 1.
requestTimestampsarrayNoRequired unless type is TOKEN_BUCKET; up to 10000 prior instants, empty for an idle subject.
bucketStateobjectNoRequired unless type is not TOKEN_BUCKET; tokens and lastRefillAt as last stored.

Output schema

FieldTypeRequiredDescription
allowedbooleanYesTrue when this request fits the policy at that instant.
reasonCodestringYesWhy the request was allowed or refused.
remainingnumberYesWhat is left for the subject; never negative.
observedintegerNoWindow types only: how many timestamps fall inside the evaluated window; omit it for TOKEN_BUCKET.
limitintegerNoWindow types only: the limit we applied; omit it for TOKEN_BUCKET.
resetAtstringNoWindow types only: when capacity next frees; omit it for TOKEN_BUCKET.
capacitynumberNoTOKEN_BUCKET only: capacity we applied; omit it for window types.
retryAfterMsintegerYesHow long to wait before this exact request would fit; 0 when allowed or when it can never fit.
nextStateobjectNoTOKEN_BUCKET only: bucket to store after this evaluation; omit it for window types.
_metaobjectNoAlways present on success: algorithm and evaluatedAt, plus window or bucket counters that apply.

API contract

POST /v1/execute
curl
curl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"network.rate_limit_check","input":{"key":"api-key:demo","policy":{"type":"FIXED_WINDOW","limit":100,"windowSeconds":60},"timestamp":"2026-07-27T10:00:30Z","requestTimestamps":[]}}'
Integrations
TypeScript SDK
import { Squillify } from "@squillify/sdk";

const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });

const { output } = await sq.execute("network.rate_limit_check", {"requestTimestamps":["2026-07-27T10:00:05Z","2026-07-27T10:00:12Z","2026-07-27T10:00:29Z"],"timestamp":"2026-07-27T10:00:30Z","key":"api-key:demo","policy":{"limit":100,"type":"FIXED_WINDOW","windowSeconds":60}});

Errors

CodeHTTPRetryableDescription
VALIDATION_ERROR400NoThe request payload failed schema validation.
UNAUTHORIZED401NoMissing or invalid API key.
SKILL_NOT_ACCESSIBLE403NoThe API key is not granted access to this skill.
SKILL_NOT_AVAILABLE_FOR_PLAN403NoThis skill is not included in your current plan.
PLAN_ELIGIBILITY_UNAVAILABLE503YesPlan eligibility could not be decided. Retry after backoff.
SKILL_NOT_FOUND404NoThe requested skill or version does not exist.
TENANT_RATE_LIMITED429YesRequest rate limit exceeded. Retry after backoff.
QUOTA_EXCEEDED429YesPlan quota exhausted. Retryable once the quota period resets.
EXECUTION_TIMEOUT504YesExecution exceeded the allowed time budget.
RATE_POLICY_INVALID400NoThe request payload failed this skill's input validation.
RATE_SNAPSHOT_INCOMPLETE400NoThe request payload failed this skill's input validation.
RATE_EVENT_LIMIT_EXCEEDED429NoA size, quota, rate, or time limit was exceeded.
RATE_TIMESTAMP_INVALID400NoThe request payload failed this skill's input validation.
RATE_ARITHMETIC_OVERFLOW429NoA size, quota, rate, or time limit was exceeded.

Other limits

LimitValue
Recommended inline bytes32 KiB

Limitations

  • Is not Squillify's own rate limiter and cannot authorize a real request
  • Does not read, reserve, consume, or mutate any live counter
  • Does not store the bucket for you — persist nextState yourself
  • Does not read a clock; the instant comes from your request
  • Does not send or inspect any HTTP traffic
  • Enforcing a limit on live traffic — the decision here is advisory
  • Counting requests for the caller; you supply the history
  • Charging Squillify quota, which is metered separately

How to call

POST /v1/execute (requires authentication)

Request bodyjson
{
  "skillKey": "network.rate_limit_check",
  "input": {
    "requestTimestamps": [
      "2026-07-27T10:00:05Z",
      "2026-07-27T10:00:12Z",
      "2026-07-27T10:00:29Z"
    ],
    "timestamp": "2026-07-27T10:00:30Z",
    "key": "api-key:demo",
    "policy": {
      "limit": 100,
      "type": "FIXED_WINDOW",
      "windowSeconds": 60
    }
  }
}

Examples

Fixed window with room left: three of a hundred used this minute

Inputjson
{
  "requestTimestamps": [
    "2026-07-27T10:00:05Z",
    "2026-07-27T10:00:12Z",
    "2026-07-27T10:00:29Z"
  ],
  "timestamp": "2026-07-27T10:00:30Z",
  "key": "api-key:demo",
  "policy": {
    "limit": 100,
    "type": "FIXED_WINDOW",
    "windowSeconds": 60
  }
}
Expected outputjson
{
  "allowed": true,
  "observed": 3,
  "retryAfterMs": 0,
  "limit": 100,
  "reasonCode": "ALLOWED",
  "resetAt": "2026-07-27T10:01:00Z",
  "_meta": {
    "evaluatedAt": "2026-07-27T10:00:30Z",
    "algorithm": "FIXED_WINDOW",
    "eventsInWindow": 3,
    "eventsConsidered": 3
  },
  "remaining": 96
}

Token bucket refilled by elapsed time, then charged four tokens

Inputjson
{
  "key": "user:42",
  "policy": {
    "refillPerSecond": 0.5,
    "type": "TOKEN_BUCKET",
    "capacity": 10
  },
  "bucketState": {
    "tokens": 2,
    "lastRefillAt": "2026-07-27T10:00:00Z"
  },
  "requestCost": 4,
  "timestamp": "2026-07-27T10:00:10Z"
}
Expected outputjson
{
  "retryAfterMs": 0,
  "nextState": {
    "tokens": 3,
    "lastRefillAt": "2026-07-27T10:00:10Z"
  },
  "allowed": true,
  "_meta": {
    "evaluatedAt": "2026-07-27T10:00:10Z",
    "algorithm": "TOKEN_BUCKET",
    "tokensBeforeRequest": 7,
    "elapsedSeconds": 10
  },
  "reasonCode": "ALLOWED",
  "remaining": 3,
  "capacity": 10
}
  • Test throttling logic against exact window edges without waiting in real time
  • Show a client how long to wait before its next call fits
  • Keep one shared rate-limit definition across services that each store their own counters

Avoid for

  • Enforcing a limit on live traffic — the decision here is advisory
  • Counting requests for the caller; you supply the history
  • Charging Squillify quota, which is metered separately

Composable with

Safety & privacy

  • Runs without calling any external service.
  • Your payloads are never stored permanently.
  • Telemetry captures metadata only — never your payload contents.
  • We never train models on your payloads.
  • No human reviews your payloads.

Tags

networkrate-limithttpvalidation