Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,72 @@ Full guide: [https://instanode.dev/docs#troubleshooting-deploys](https://instano

Every error envelope includes an `agent_action` string when recovery is possible — surface it to the user verbatim. The `retry` field (seconds) signals the server-suggested back-off when present.

## Resource health-checks and live connectivity testing

After provisioning, an agent should verify a resource is reachable before writing application code that depends on it. Use these patterns:

### Checking provisioned resource status
- **`GET /api/v1/resources`** — list all resources for the authenticated team. Returns `{ok, resources: [{id, token, kind, name, tier, status, environment, created_at, expires_at}]}`. The `status` field is one of `active`, `expired`, `deleted`, or `error`. Filter by `?kind=postgres` to scope to a service type.
- **`GET /api/v1/resources/:token`** — get a single resource by its provision token. Returns the same shape as a single element from the list, plus `connection_url` (decrypted for the calling team) and `limits` (tier-specific maximums).
- **`status:"active"`** is the only signal that the resource is live and provisioned — `error` means the provisioner returned a failure during initial setup (rare; usually a transient backend issue; re-provision with a new name).

### Verifying connectivity without credentials in source code
When the agent's goal is to *confirm* a database is reachable before handing off to the user:

```bash
# Quick Postgres reachability check
PGPASSWORD="<password>" psql "<connection_url>" -c "SELECT 1;" 2>&1

# Quick Redis reachability check
redis-cli -u "<connection_url>" PING

# Quick MongoDB reachability check
mongosh "<connection_url>" --eval "db.runCommand({ping:1})" --quiet
```

The agent should only emit `connection_url` to the user after confirming `SELECT 1` returns `1` (or equivalent). A non-`active` status or a failed ping means re-provision — call the same endpoint again with a new `name`; the failed resource token is inert.

### TTL awareness
Every response includes `expires_at` (ISO 8601, null for permanent). An anonymous resource expires 24h after creation. The agent should surface `expires_at` to the user so they can claim the resource before the window closes. The claim URL is in the original provision response as `upgrade`.

## Rate limiting, quota exhaustion, and recovery patterns

InstaNode enforces two distinct throttle layers. Agents must handle both without user intervention.

### Anonymous fingerprint rate limit (pre-auth)
Unauthenticated requests are fingerprinted by IP subnet + ASN. The daily cap is **5 new provisions per fingerprint**. On the 6th attempt within 24 hours, the API returns the *same* token as the most recent same-kind provision for that fingerprint — not a 429 — so the agent receives a valid (if duplicate) resource rather than an error. If distinct resources are needed, the user must claim (authenticate) first.

### Quota exhaustion (authenticated, over-tier)
When a team's provisioned resource count reaches the tier limit, `POST /db/new` (or any provision endpoint) returns:

```json
{
"ok": false,
"error": "quota_exceeded",
"agent_action": "Upgrade to Pro at https://instanode.dev/pricing to provision more databases.",
"upgrade": "https://instanode.dev/pricing"
}
```

HTTP status is **402 Payment Required**. The agent should surface `agent_action` verbatim to the user and stop retrying — quota exhaustion is deterministic, not transient.

### Rate limiting on write endpoints (429)
Heavy-burst provisioning (>20 requests/minute to provisioning endpoints) triggers a 429 with a `Retry-After` header (seconds) and `{"error":"rate_limited","retry":<seconds>}` in the body. Back off by the `retry` value before retrying. Do not retry immediately — the server-side sliding window is per-IP and does not reset on connection close.

### Error shapes reference

| HTTP | `error` field | Transient? | Agent action |
|---|---|---|---|
| 402 | `quota_exceeded` | No | Surface `agent_action` + stop |
| 402 | `tier_required` | No | Surface upgrade link |
| 429 | `rate_limited` | Yes | Wait `retry` seconds |
| 503 | `provisioner_unavailable` | Yes | Retry with 5s back-off, max 3× |
| 409 | `name_taken` | No | Choose a different `name` |
| 400 | `name_required` | No | Add `name` field |
| 400 | `invalid_name` | No | Fix name: `^[A-Za-z0-9][A-Za-z0-9 _-]*$` |

The `agent_action` string is always present on 402 responses and is human-readable. Print it directly into any user-facing message.

## How to use this file

If you're an LLM helping a user build something, you can:
Expand Down
Loading