From 075fe118f11dedd999dec48d831cd4a0c8674dc4 Mon Sep 17 00:00:00 2001
From: Hyo
+ The official hosted IAPKit service is open-source infrastructure
+ shared by the OpenIAP community. It is free under fair-use safeguards
+ and operated on a best-effort basis; it is not unlimited capacity and
+ does not include dedicated resources or an SLA.
+
+ Plan from request frequency and peak concurrency, not DAU alone. One
+ million users making one hosted request per day already averages about{' '}
+ 11.6 requests per second, before cold-start,
+ release-day, or notification-driven peaks. That average exceeds the
+ hosted default per-key steady rate of 10 requests per second.
+
+ Hosted purchase verification also limits work already in progress to{' '}
+
+ 8 handlers per API key, 16 per trusted source IP, and 32 per process
+
+ . The key and source shares make simple credential rotation
+ insufficient to monopolize the process from one network source;
+ requests beyond any axis receive
+ Contact us before a high-volume production launch.{' '}
+ If your organization expects to consume a meaningful share of hosted
+ capacity, we ask it to help fund server expansion, monitoring,
+ security, and load testing through{' '}
+
+ GitHub Sponsors
+ {' '}
+ or{' '}
+
+ OpenCollective
+
+ . Sponsorship supports shared capacity; it does not automatically
+ reserve dedicated resources or create an SLA.
+
+ For predictable capacity and full operational control,{' '}
+
+ self-host the MIT-licensed server
+
+ . For capacity planning or a separate written arrangement, contact{' '}
+ hyo@hyo.dev.
+
+ The official
+ If your organization expects sustained high volume or would use a
+ meaningful share of that capacity, we ask you to contact us before
+ launch and help fund the servers, monitoring, security, and load
+ testing your traffic requires. You can contribute through{' '}
+
+ GitHub Sponsors
+ {' '}
+ or{' '}
+
+ OpenCollective
+
+ .
+
+ Sponsorship strengthens shared capacity for everyone; it does not
+ automatically buy unlimited usage, dedicated resources, or an SLA.
+ Teams that need predictable scaling or full operational control
+ can{' '}
+
+ self-host the MIT-licensed server
+ {' '}
+ or contact{' '}
+
+ hyo@hyo.dev
+ {' '}
+ about a separate written arrangement.
+ 503 SERVICE_BUSY instead
+ of entering an unbounded server queue.
+
+
+ 429 and 503 Retry-After with
+ jittered backoff. A 304 saves response transfer but
+ still uses a Convex query invocation.
+
+ Keep Hosted IAPKit Shared and Sustainable
+
+ kit.openiap.dev service runs the
+ open-source IAPKit backend as shared infrastructure for the whole
+ ecosystem. It is free under fair-use safeguards, best-effort, and
+ intentionally available to developers who cannot operate a
+ receipt-validation server themselves.
+
Why AI Can't Replace This Work
@@ -251,7 +332,8 @@ function Sponsors() {
>
GitHub Sponsors is the primary funding channel. Tiers scale from
individual contributors to companies shipping OpenIAP in
- production — details are on the GitHub page.
+ production. OpenCollective is also available for transparent
+ community funding.
{ - "Thank you for supporting IAPKit. Your subscription has been cancelled and any unused portion refunded in full — there's nothing you need to do. The validation APIs and analytics you were using keep working." + "Thank you for supporting IAPKit. Your subscription has been cancelled and any unused portion refunded in full — there's nothing you need to do. The validation APIs and analytics you were using keep working under the shared hosted service's fair-use safeguards." }
{ - "Track validation usage and stored receipt analytics. Validation and analytics are free." + "Track validation usage and stored receipt analytics. Hosted IAPKit is free under fair-use limits on shared community infrastructure." }
{ - "Validation and analytics stay free for every developer. If your team or company depends on them, consider supporting the project so we can keep the core service running for thousands of indie developers." + "Hosted IAPKit is a shared, best-effort service rather than unlimited or SLA-backed infrastructure. If your organization expects to consume a meaningful share of capacity, contact us before launch and help fund the servers, monitoring, and security the ecosystem depends on." }
{ - "AI-assisted workflows may later use separate usage-based pricing because model token costs are real infrastructure costs." + "Sponsorship supports shared capacity; it does not automatically reserve dedicated resources or an SLA. Self-host the MIT-licensed server when you need predictable capacity and full operational control." }
- - {"Become a sponsor"} - + ++ {"Capacity planning: "} + + hyo@hyo.dev + +
304, replace it on{" "}
- 200, and respect 429 Retry-After.
+ 200, and respect 429 or{" "}
+ 503 Retry-After.
Every authenticated response (2xx, validation 4xx, 429) carries:
++ Every authenticated response after the auth layer carries the + correlation and rate-limit headers below: +
X-Correlation-Id — UUID for this request. Quote it in
@@ -510,7 +514,12 @@ async function refreshEntitlements(
- On 429 the response also carries Retry-After in seconds.
+ Verification responses that pass body validation also carry{" "}
+ X-Concurrency-Limit and{" "}
+ X-Concurrency-Remaining. X-Concurrency-Scope{" "}
+ identifies the reported API-key, trusted source-IP, or process-global
+ axis. A 429 or application-generated 503 response carries{" "}
+ Retry-After in seconds.
401 / 403 responses from the auth layer run before the rate-limit @@ -591,6 +600,15 @@ async function refreshEntitlements( Retry-After. +
- /v1/purchase/verify is protected by an in-memory
- token-bucket keyed on a SHA-256 hash of the API key. Defaults:
- 600-request burst, 10 req/sec steady state —
- equivalently 600 req/min sustained. Self-hosted deployments can tune via{" "}
- RATE_LIMIT_CAPACITY and{" "}
- RATE_LIMIT_REFILL_PER_SEC.
+ Publishable-key routes are protected by bounded, in-memory token
+ buckets. Defaults are 600 burst / 10 req/sec per API
+ key, 600 burst / 5 req/sec per source IP, and{" "}
+ 5,000 burst / 100 req/sec for the whole process.
+ Self-hosted deployments can tune the RATE_LIMIT_*{" "}
+ environment variables.
When the bucket empties, IAPKit returns 429 RATE_LIMITED{" "}
@@ -42,6 +42,80 @@ export default function OperationsPage() {
+ Arrival rate and work already in progress are different limits. A slow
+ Apple, Google, Amazon, Meta, or Convex response can make accepted
+ verifications overlap, so each API key may occupy at most{" "}
+ 8 verification handlers, each trusted source IP at most{" "}
+ 16, and each process at most 32 by
+ default. The key and source shares make simple credential rotation
+ insufficient to monopolize the process from one network source. Excess
+ work is not queued in memory; it returns 503 SERVICE_BUSY{" "}
+ with Retry-After, X-Concurrency-Limit,{" "}
+ X-Concurrency-Remaining, and{" "}
+ X-Concurrency-Scope.
+
+ Self-hosters can tune VERIFY_MAX_IN_FLIGHT,{" "}
+ VERIFY_MAX_IN_FLIGHT_PER_KEY, and{" "}
+ VERIFY_MAX_IN_FLIGHT_PER_IP. Fly Proxy also uses request
+ concurrency limits for the whole HTTP service (80 soft, 120 hard per
+ machine) so static, read, and verification traffic cannot create an
+ unbounded number of requests inside one 512 MB machine.
+
+ Hosted IAPKit is open-source infrastructure shared by the OpenIAP + community. It is free without a request billing meter, best-effort, and + protected by fair-use safeguards; it is not unlimited capacity and does + not include dedicated resources or an SLA. +
+
+ One million users making one request per day average about 11.6
+ requests per second, already above the hosted default per-key steady
+ rate before launch-time or notification-driven peaks. Cache stable
+ data, coalesce refreshes, verify only after purchase or restore, and
+ honor 429 and 503 Retry-After with jittered
+ backoff.
+
+ If your organization expects sustained high volume or a meaningful share + of hosted capacity, contact{" "} + + hyo@hyo.dev + {" "} + before launch. We ask organizations at that scale to help fund shared + capacity, monitoring, security, and load testing through{" "} + + GitHub Sponsors + {" "} + or{" "} + + OpenCollective + + . Sponsorship strengthens the shared service; it does not automatically + reserve capacity or create an SLA. For predictable scaling, self-host + the MIT-licensed server. +
+Every verify response after the auth-header shape check carries an{" "} diff --git a/packages/kit/src/pages/landing.tsx b/packages/kit/src/pages/landing.tsx index 3da488c1e..f5a51eecf 100644 --- a/packages/kit/src/pages/landing.tsx +++ b/packages/kit/src/pages/landing.tsx @@ -81,7 +81,9 @@ export default function LandingPage() {
- {"Validation and analytics are free for every developer."} + { + "Hosted validation and analytics are free under fair-use limits." + }
- {"No credit card for validation or analytics."} + { + "No credit card. Shared, community-funded infrastructure with best-effort availability." + }
@@ -242,44 +246,92 @@ export default function LandingPage() { - {/* Sponsorship Section */} + {/* Shared capacity and sponsorship section */}+
{ - "Core IAPKit validation and analytics are free for every developer. If your team depends on them, help sustain the project — every contribution keeps the foundation available for thousands of indie developers." + "Hosted IAPKit is an open-source community service that every developer can share. It has fair-use rate limits, does not include an SLA, and is not unlimited infrastructure." }
-- { - "Advanced AI-assisted workflows may be handled separately later, because model token costs are real infrastructure costs." - } -
-+ { + "Use the hosted service without a billing meter, cache reads responsibly, and honor 429 or 503 retry guidance so capacity remains available to everyone." + } +
++ { + "Contact us before launch. If your organization expects to consume a meaningful share of the hosted capacity, we ask it to help fund server expansion, monitoring, and security for the ecosystem." + } +
++ { + "Self-host the MIT-licensed server for predictable capacity and operational control. Sponsorship supports the shared service; it does not automatically include dedicated resources or an SLA." + } +
++ { + "For capacity planning or a separate written service agreement, contact " + } + + hyo@hyo.dev + + {" before your production launch."} +
429 and 503 Retry-After with
- jittered backoff. A 304 saves response transfer but
- still uses a Convex query invocation.
+ Honor the Retry-After header on 429 and{' '}
+ 503 with jittered backoff. A 304 saves
+ response transfer but still uses a Convex query invocation.
304, replace it on{" "}
- 200, and respect 429 or{" "}
- 503 Retry-After.
+ 200, and respect the Retry-After header on{" "}
+ 429 or 503.
429 and 503 Retry-After with jittered
- backoff.
+ honor the Retry-After header on 429 and{" "}
+ 503 with jittered backoff.
From 024e8d4470e33145460b6efad79fae4fec2d432d Mon Sep 17 00:00:00 2001
From: Hyo
- Every authenticated response after the auth layer carries the
- correlation and rate-limit headers below:
+ Verification requests that pass bearer-token shape validation carry a
+ correlation ID. Requests that reach the multi-axis rate limiter also
+ carry its limit and remaining-token headers:
- Verification responses that pass body validation also carry{" "}
+ Verification responses that reach the in-flight guard also carry{" "}
401 / 403 responses from the auth layer run before the rate-limit
@@ -596,7 +598,9 @@ async function refreshEntitlements(
REPEATED_FAILURE
Response headers
X-Concurrency-Limit and{" "}
X-Concurrency-Remaining. X-Concurrency-Scope{" "}
identifies the reported API-key, trusted source-IP, or process-global
- axis. A 429 or application-generated 503 response carries{" "}
- Retry-After in seconds.
+ axis. A RATE_LIMITED response names its key, IP, or process
+ bucket in X-RateLimit-Scope. A 429 or application-generated
+ 503 response carries Retry-After in seconds.
- Per-key or per-payload guard rejected the request; check
+ RATE_LIMITED names the rejecting API-key, source-IP, or process
+ bucket in X-RateLimit-Scope. DUPLICATE_PAYLOAD and
+ REPEATED_FAILURE are per-(key, payload) replay guards. Check
Retry-After.