Skip to content
Skillv1.0.0

flyio-rate-limits

Handle Fly.io Machines API rate limits with backoff, concurrency control, and request batching for machine management operations. Trigger: "fly.io rate limit", "fly.io 429", "fly.io throttling", "mach

by jeremylongshore(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from jeremylongshore/tons-of-skills-marketplace (skills/.curated/flyio-rate-limits/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill flyio-rate-limits. Copyright stays with the author (MIT).

Fly.io Rate Limits

Overview

The Fly.io Machines API rate-limits per organization, with write operations (create, delete, update) throttled much more aggressively than reads. Deploying fleets of edge machines across multiple regions can easily trigger 429s, especially during rolling deployments or auto-scaling events. The API returns a Retry-After header on rate-limited responses, and organizations running 50+ machines should implement client-side token bucket limiting to avoid cascading failures during high-churn operations.

Prerequisites

  • Current platform limits confirmed for the organization plus approved concurrency, retry bounds, and a queue owner.
  • Redacted telemetry for request category, queue age, throttle count, and machine lifecycle—not tokens or payloads.
  • A staging fleet/synthetic workload for testing pauses, retries, and cancellation.

Instructions

  1. Honor explicit throttling guidance and use bounded concurrency with jittered backoff.
  2. Attach idempotency/operation tracking to lifecycle changes so a retry cannot duplicate a create, stop, or delete action.
  3. Queue exhausted operations for reviewed handling, alert on backlog growth, and reduce demand before resuming.

Output

Publish a rate-control receipt with policy version, concurrency, retry bounds, throttle count, queue outcome, owner, and manual disposition. Do not expose app names if they are sensitive, tokens, or request bodies.

Examples

Apply a small synthetic scale change, simulate a 429, and confirm the worker waits and then performs the operation once. A repeated failure must enter the review queue rather than trigger a fleet-wide replay.

Rate Limit Reference

Endpoint Limit Window Scope
Machine create/delete 10 req 1 minute Per org
Machine start/stop 30 req 1 minute Per org
Machine list/get 120 req 1 minute Per org
App create/delete 5 req 1 minute Per org
Volume operations 15 req 1 minute Per org

Rate Limiter Implementation

class FlyRateLimiter {
  private tokens: number;
  private lastRefill: number;
  private readonly max: number;
  private readonly refillRate: number;
  private queue: Array<{ resolve: () => void }> = [];

  constructor(maxPerMinute: number) {
    this.max = maxPerMinute;
    this.tokens = maxPerMinute;
    this.lastRefill = Date.now();
    this.refillRate = maxPerMinute / 60_000;
  }

  async acquire(): Promise<void> {
    this.refill();
    if (this.tokens >= 1) { this.tokens -= 1; return; }
    return new Promise(resolve => this.queue.push({ resolve }));
  }

  private refill() {
    const now = Date.now();
    this.tokens = Math.min(this.max, this.tokens + (now - this.lastRefill) * this.refillRate);
    this.lastRefill = now;
    while (this.tokens >= 1 && this.queue.length) {
      this.tokens -= 1;
      this.queue.shift()!.resolve();
    }
  }
}

const writeLimiter = new FlyRateLimiter(8);  // leave headroom under 10/min
const readLimiter = new FlyRateLimiter(100);

Retry Strategy

async function flyRetry<T>(fn: () => Promise<Response>, maxRetries = 4): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const res = await fn();
    if (res.ok) return res.json();
    if (res.status === 429) {
      const retryAfter = parseInt(res.headers.get("Retry-After") || "10", 10);
      const delay = retryAfter * 1000 + Math.random() * 2000;
      await new Promise(r => setTimeout(r, delay));
      continue;
    }
    if (res.status >= 500 && attempt < maxRetries) {
      await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
      continue;
    }
    throw new Error(`Fly API ${res.status}: ${await res.text()}`);
  }
  throw new Error("Max retries exceeded");
}

Batch Processing

async function rollingDeployMachines(appId: string, configs: any[], batchSize = 3) {
  const results: any[] = [];
  for (let i = 0; i < configs.length; i += batchSize) {
    const batch = configs.slice(i, i + batchSize);
    const batchResults = await Promise.all(
      batch.map(async cfg => {
        await writeLimiter.acquire();
        return flyRetry(() =>
          fetch(`https://api.machines.dev/v1/apps/${appId}/machines`, {
            method: "POST", headers, body: JSON.stringify(cfg),
          })
        );
      })
    );
    results.push(...batchResults);
    if (i + batchSize < configs.length) await new Promise(r => setTimeout(r, 10_000));
  }
  return results;
}

Error Handling

Issue Cause Fix
429 on machine create Exceeded 10 writes/min org limit Use Retry-After header, batch deploys
429 on fleet list Monitoring polling too fast Cache responses, poll every 30s max
Timeout on volume attach Volume in another region Verify region match before attach
503 during region outage Specific edge region down Fail over to secondary region
409 on machine update Concurrent config change Re-fetch machine state, retry with latest version

Resources

Next Steps

See flyio-performance-tuning.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/jeremylongshore-tons-of-skills-marketplace-flyio-rate-limits/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

jeremylongshore-tons-of-skills-marketplace-flyio-rate-limits.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-flyio-rate-limits",
  "kind": "skill",
  "name": "flyio-rate-limits",
  "description": "Handle Fly.io Machines API rate limits with backoff, concurrency control, and request batching for machine management operations. Trigger: \"fly.io rate limit\", \"fly.io 429\", \"fly.io throttling\", \"machines API limit\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "saas",
      "edge-compute",
      "flyio",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Handle Fly.io Machines API rate limits with backoff, concurrency control, and request batching for machine management operations. Trigger: \"fly.io rate limit\", \"fly.io 429\", \"fly.io throttling\", \"machines API limit\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "skills/.curated/flyio-rate-limits/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/skills/.curated/flyio-rate-limits/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/skills/.curated/flyio-rate-limits/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit"
    ],
    "license": "MIT"
  },
  "instructions": "# Fly.io Rate Limits\n\n## Overview\n\nThe Fly.io Machines API rate-limits per organization, with write operations (create, delete, update) throttled much more aggressively than reads. Deploying fleets of edge machines across multiple regions can easily trigger 429s, especially during rolling deployments or auto-scaling events. The API returns a `Retry-After` header on rate-limited responses, and organizations running 50+ machines should implement client-side token bucket limiting to avoid cascading failures during high-churn operations.\n\n## Prerequisites\n\n- Current platform limits confirmed for t",
  "cost": {
    "context_tokens": 1306
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-flyio-rate-limits/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.