REST API, GraphQL API, gh api, Pagination, Rate Limits, and Automation Clients: Configuration, Design Choices, and Tradeoffs
Choose deliberately among REST, GraphQL, first-class gh commands, gh api, curl, and SDKs; design pagination, polling, webhook, identity, observability, and mutation policies around maintainability, security, reliability, compatibility, and cost.
Learning objectives
-
Select REST, GraphQL, or a first-class
ghcommand based on contract fit. -
Compare
gh api, curl, and SDK/Octokit-style clients for prototypes and production. - Design REST Link and GraphQL cursor traversal without partial-result assumptions.
- Choose polling versus webhooks based on freshness, reliability, rate, and ownership.
- Define identity, field minimization, compatibility, observability, and mutation governance.
1. REST versus GraphQL versus first-class gh
| Need | Prefer | Why |
|---|---|---|
| Maintained operator task | First-class gh command |
Built-in UX/auth and often structured --json;
less custom code.
|
| One resource/collection | REST | Clear resource/status semantics and straightforward conditional GET behavior. |
| Related fields across resources | GraphQL | Client-defined typed shape can reduce request count. |
| No first-class CLI command | gh api |
Direct access to documented REST/GraphQL while reusing gh auth/host handling. |
Do not parse decorative CLI tables if --json or a
documented API exists. Likewise, do not choose GraphQL simply
because it is more expressive; use the smallest stable contract that
makes correctness obvious.
2. gh api versus curl versus SDK/Octokit-style client
| Client | Strength | Tradeoff |
|---|---|---|
gh api |
Fast operator/prototype path; auth, host, pagination, jq/templates. | Shell quoting and larger testable workflows become cumbersome. |
| curl | Transparent raw HTTP and useful unauthenticated/protocol debugging. | You own auth, JSON, pagination, retries, parsing, logging, redaction. |
| SDK/Octokit-style | Pagination helpers, language integration, tests/types. | Another supply-chain dependency; still need endpoint/rate/idempotence understanding. |
3. Page/Link versus cursor traversal
REST clients should follow GitHub-provided
Link relations rather than assume page+1.
GraphQL cursors are opaque: pass them back; never decode them or
infer business meaning. Both clients need termination rules,
page-count metrics, and a policy for data changing during traversal.
“Fetched all pages” does not necessarily mean “observed one atomic snapshot.” If consistency matters, use stable IDs/filters/timestamps where supported and define the reconciliation semantics explicitly.
4. Polling versus webhook/event-driven integration
| Criterion | Polling | Webhook/event |
|---|---|---|
| Bootstrap/current snapshot | Strong for full enumeration. | Does not inherently provide history before subscription. |
| Fast change signal | Requires frequent calls and rate budget. | Strong when the needed event exists. |
| Recovery | Next reconciliation can recover missed state. | Receiver must handle signature verification, retries/redelivery, duplicates, and ordering assumptions. |
| Complexity | Simple at low frequency; conditional GET helps. | Needs reachable receiver, delivery storage/observability, replay-safe processing. |
A robust integration often combines webhook change signals with periodic read-only reconciliation. Chapter 27 covers webhook/App mechanics; Chapter 26 establishes why aggressive polling is not the default when an event exists.
5. Identity and least privilege
Pick identity before endpoint code. Interactive tooling may
appropriately use the logged-in gh user. Long-running
organization automation often benefits from a GitHub App
installation token because repository selection and permissions can
be narrowly modeled and tokens are short-lived. Inside Actions, use
explicit GITHUB_TOKEN permissions where it is
sufficient.
Least privilege also applies to fields. A GraphQL identity that can read sensitive organization data does not mean the query should select it. Request only what the decision needs; avoid storing complete response bodies by default.
6. GitHub.com versus Enterprise Server and API compatibility
REST 2026-03-10 is the current course contract for
GitHub.com. GraphQL has schema deprecations/changelog rather than
the REST version header. GHES uses its own host/API base and release
cadence; site administrators can configure rate limits, and
fields/features can differ.
api.github.com assumptions in reusable clients.
7. Worked architecture decision: organization repository inventory
| Dimension | Choice | Justification |
|---|---|---|
| Maintainability | GitHub App + SDK | Distinct automation identity and testable code. |
| Security | Metadata-read on selected repositories | Limits blast radius and data exposure. |
| Governance | GraphQL bootstrap + webhook + periodic reconciliation | Fast changes plus durable full-state correction. |
| Reliability | Cursor traversal, error rejection, delivery dedupe, backoff | Avoids partial state and duplicate processing. |
| Compatibility | Host/schema feature probe | Does not silently assume GitHub.com features on GHES. |
| Cost/performance | Minimize selected fields and polling | Reduces rate pressure and processing/storage load. |
8. Production client policy template
- Owner: team responsible for API/schema upgrades and incidents.
- Identity: App/GITHUB_TOKEN/user tool plus exact permissions/repository selection.
- Host contract: GitHub.com or supported GHES versions, REST version, GraphQL schema checks.
- Traversal: endpoint/connection, page size, termination, page metrics, partial-error behavior.
- Rate policy: concurrency cap, Retry-After/reset handling, maximum retry horizon, event alternative.
- Mutation policy: dry-run, desired-state key, duplicate check/precondition, post-write verification.
- Observability: request ID, operation, status, duration, pages/items, rate remaining; no token/body dumps.
Knowledge check
Should GraphQL be the default for adding one label just because it supports mutations?
No. A first-class gh command or a simple REST endpoint may be smaller, clearer, and easier to operate.
Why can webhook-only inventory be incomplete?
A webhook gives delivered events after subscription, not a guaranteed full historical/current snapshot. Bootstrap and reconciliation reads are still useful.
What is wrong with selecting every GraphQL field “just in case”?
It increases data exposure, query cost, storage/logging risk, and complexity. Least privilege includes data selection.
Why must the API host be configurable?
GHES uses a different host/base URL and may expose different versions/features. Hard-coding GitHub.com reduces portability and can target the wrong deployment.
An SDK supports automatic retries. Is it safe for every POST?
No. Transport retries do not provide application idempotence. Re-read desired state before repeating non-idempotent creates.
Summary
API surface choice is architecture: use the smallest stable contract, combine event signals with reconciliation where appropriate, minimize identity/data scope, and make host/version/pagination/rate/mutation policy explicit.
Official references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.