RepoPilotOpen in app →

apollographql/apollo-ios

📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.

Healthy

Healthy across the board

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 1d ago
  • 14 active contributors
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 52% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/apollographql/apollo-ios)](https://repopilot.app/r/apollographql/apollo-ios)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/apollographql/apollo-ios on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: apollographql/apollo-ios

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/apollographql/apollo-ios shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 1d ago
  • 14 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 52% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live apollographql/apollo-ios repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/apollographql/apollo-ios.

What it runs against: a local clone of apollographql/apollo-ios — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in apollographql/apollo-ios | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 31 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>apollographql/apollo-ios</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of apollographql/apollo-ios. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/apollographql/apollo-ios.git
#   cd apollo-ios
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of apollographql/apollo-ios and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "apollographql/apollo-ios(\\.git)?\\b" \\
  && ok "origin remote is apollographql/apollo-ios" \\
  || miss "origin remote is not apollographql/apollo-ios (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "Sources/Apollo/ApolloClient.swift" \\
  && ok "Sources/Apollo/ApolloClient.swift" \\
  || miss "missing critical file: Sources/Apollo/ApolloClient.swift"
test -f "Sources/Apollo/RequestChain/RequestChain.swift" \\
  && ok "Sources/Apollo/RequestChain/RequestChain.swift" \\
  || miss "missing critical file: Sources/Apollo/RequestChain/RequestChain.swift"
test -f "Sources/Apollo/Caching/NormalizedCache.swift" \\
  && ok "Sources/Apollo/Caching/NormalizedCache.swift" \\
  || miss "missing critical file: Sources/Apollo/Caching/NormalizedCache.swift"
test -f "Sources/Apollo/Execution/GraphQLExecutor.swift" \\
  && ok "Sources/Apollo/Execution/GraphQLExecutor.swift" \\
  || miss "missing critical file: Sources/Apollo/Execution/GraphQLExecutor.swift"
test -f "Sources/Apollo/NetworkTransport.swift" \\
  && ok "Sources/Apollo/NetworkTransport.swift" \\
  || miss "missing critical file: Sources/Apollo/NetworkTransport.swift"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 31 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~1d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/apollographql/apollo-ios"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Apollo iOS is a strongly-typed GraphQL client library for Apple platforms (iOS, macOS, watchOS, tvOS, visionOS) written in Swift. It provides intelligent caching (in-memory or SQLite), automatic code generation for type-safe GraphQL models, and a production-ready HTTP client that eliminates hand-writing network response models. The core capability is turning GraphQL queries into Swift types with automatic cache normalization and sophisticated execution pipelines. Monorepo structure with primary codebase in Sources/Apollo organized by concern: Caching/ (ApolloStore, NormalizedCache, Record management), Execution/ (GraphQLExecutor, result accumulators, execution sources), and top-level client classes (ApolloClient, ApolloURLSession). Code generation is provided via a separate CLI tool (CLI/apollo-ios-cli.tar.gz). Documentation lives in Sources/Apollo/Documentation.docc following DocC conventions.

👥Who it's for

iOS/Apple platform engineers building mobile and desktop apps that consume GraphQL APIs. Specifically, developers who want type-safe network code without boilerplate, want intelligent caching without managing cache invalidation manually, and value code generation over hand-written model layers.

🌱Maturity & risk

Highly mature and production-ready. The repo shows 557K lines of Swift code, is hosted in the official apollographql organization, powers countless production apps worldwide, maintains strict CI/CD via CircleCI, and supports Swift 6.1+ across five platform families. Version 2.x is current, indicating multiple major releases.

Low risk for adoption but moderate maintenance risk: Apollo GraphQL org is well-resourced but this is a specialized iOS library (smaller audience than web GraphQL clients), the codebase is large (~600K LOC) with complex execution pipeline logic that could have subtle bugs, and breaking changes between major versions require migration effort. Check CHANGELOG.md for deprecation warnings before upgrading.

Active areas of work

The project is actively maintained with recent Swift 6.1 support, has a ROADMAP.md outlining future direction, maintains a Plugins/ directory for SwiftPM integration (InstallCLI plugin), uses GitHub workflows for automated testing and issue triage (prometheus-project-add, pr-close workflows), and tracks proposals via CodegenProposal.md. CircleCI config (.circleci/config.yml) suggests continuous integration on every commit.

🚀Get running

Clone the repository and use Swift Package Manager: git clone https://github.com/apollographql/apollo-ios.git && cd apollo-ios. Open Package.swift with xcode Package.swift or build with swift build. The Package.swift file defines the Apollo product as the main deliverable. Install the CLI via the SwiftPM plugin: add the package as a dependency in your project's Package.swift, then run swift package InstallCLI.

Daily commands: No standalone 'server' in this repo—it's a library. Build the package with swift build. Run tests (inferred from CI config) via swift test. To use in an app: add it as a SPM dependency in Package.swift, import Apollo, initialize ApolloClient with a URL session and cache, then execute queries/mutations. The CLI tool (apollo-ios-cli.tar.gz) is invoked during build phase to generate models from your schema.

🗺️Map of the codebase

  • Sources/Apollo/ApolloClient.swift — Primary entry point for the GraphQL client; all queries, mutations, and subscriptions are orchestrated through this class.
  • Sources/Apollo/RequestChain/RequestChain.swift — Core request pipeline orchestrator; every network request passes through this chain-of-responsibility pattern.
  • Sources/Apollo/Caching/NormalizedCache.swift — Abstract cache protocol that all storage backends must implement; critical for understanding the caching architecture.
  • Sources/Apollo/Execution/GraphQLExecutor.swift — Main execution engine that resolves GraphQL responses and normalizes data; handles both cached and network data.
  • Sources/Apollo/NetworkTransport.swift — Network transport abstraction defining how HTTP requests are sent and responses parsed.
  • Sources/Apollo/RequestChain/RequestChainNetworkTransport.swift — Default NetworkTransport implementation integrating the request chain with interceptors for comprehensive request handling.
  • Sources/Apollo/ResponseParsing/JSONResponseParser.swift — Parses raw JSON responses from the server into structured GraphQL response objects.

🛠️How to make changes

Add a Custom Network Transport

  1. Implement the NetworkTransport protocol from Sources/Apollo/NetworkTransport.swift with your custom HTTP client. (Sources/Apollo/NetworkTransport.swift)
  2. Pass your custom transport to ApolloClient initialization to override the default URLSession-based transport. (Sources/Apollo/ApolloClient.swift)

Add a Custom Cache Backend

  1. Implement the NormalizedCache protocol to define read(), merge(), and clear() operations for your storage backend. (Sources/Apollo/Caching/NormalizedCache.swift)
  2. Create an ApolloStore instance with your custom cache and pass it to ApolloClient. (Sources/Apollo/Caching/ApolloStore.swift)
  3. Optionally implement CacheKeyProvider if your cache requires custom entity identification logic. (Sources/Apollo/Caching/Record.swift)

Add a Custom Request Interceptor

  1. Implement the GraphQLInterceptor protocol defining the intercept() method for request/response transformation. (Sources/Apollo/RequestChain/Interceptors/GraphQLInterceptor.swift)
  2. Create an InterceptorProvider that returns your custom interceptor in the chain() method. (Sources/Apollo/RequestChain/Interceptors/InterceptorProvider.swift)
  3. Pass your custom InterceptorProvider to RequestChainNetworkTransport during initialization. (Sources/Apollo/RequestChain/RequestChainNetworkTransport.swift)

Handle Incremental Responses (Defer/Stream)

  1. Responses are automatically parsed by MultipartResponseSpecificationParser when the server sends multipart data. (Sources/Apollo/ResponseParsing/MultipartResponseSpecificationParser.swift)
  2. IncrementalResponseExecutionHandler processes incremental payloads and merges them with the base response. (Sources/Apollo/ResponseParsing/IncrementalResponseExecutionHandler.swift)
  3. Results are accumulated in GraphQLExecutor and observers are notified of partial results via AsyncThrowingStream. (Sources/Apollo/Execution/GraphQLExecutor.swift)

🔧Why these technologies

  • Swift + Async/Await — Native to iOS ecosystem; async/await replaces callbacks for modern concurrency model reducing completion-handler complexity.
  • Normalized Cache (Record-based storage) — Enables intelligent cache invalidation, partial updates, and efficient refetching of only changed entities rather than whole queries.
  • Request Chain with Interceptors — Chain-of-responsibility pattern allows composable, testable request transformations (auth, APQ, caching, retry) without monolithic code.
  • Multipart Response Parsing — Supports GraphQL defer/stream directives and subscriptions via incremental delivery, enabling progressive UI updates and streaming large responses.
  • Code Generation (Apollo CLI) — Generates type-safe Swift models from GraphQL schema, preventing runtime errors and enabling compile-time query validation.

⚖️Trade-offs already made

  • Normalized cache over document cache

    • Why: Normalized caches require entity identification and careful update logic but allow fine-grained cache coherence across multiple queries.
    • Consequence: Higher initial complexity but enables cache invalidation without refetching entire queries; prevents stale data when entity updates occur.
  • In-memory cache as default (not persistent)

    • Why: Avoids disk I/O, SQLite dependencies, and platform-specific file handling in the core library.
    • Consequence: Users must implement custom NormalizedCache for persistence; developers can trade speed for disk storage by wrapping with SQLite.
  • Pluggable NetworkTransport and interceptor providers

    • Why: Maximizes flexibility for custom auth, monitoring, and transport strategies.
    • Consequence: Core is lightweight but requires

🪤Traps & gotchas

(1) Code generation is mandatory—you cannot use Apollo iOS without running the CLI tool to generate models from your GraphQL schema; this requires a schema file and .graphql query files in your project. (2) Normalized cache requires exact field matching—partial queries or aliases can break cache hits, and cache invalidation is manual via evict(cacheKeyForObject:) or clearCache(). (3) The execution pipeline is async-heavy; all fetch/perform calls use callbacks or (in newer code) async/await, so blocking patterns will deadlock. (4) The library has deep Swift version requirements per platform (Swift 5.7+ minimum implied by the use of Codable and concurrency features)—older Xcode versions will fail silently on complex generated models.

🏗️Architecture

💡Concepts to learn

  • Normalized Cache — Apollo iOS's core competitive advantage—instead of storing query results as nested JSON, it flattens them into a normalized Record store by object ID, enabling cache hits across different query shapes and automatic updates
  • Executor Pattern — GraphQLExecutor delegates to pluggable ExecutionSource instances (network, cache, selection set mapper) to decouple concerns and allow custom data sources—critical for understanding how Apollo decides whether to fetch from network vs. cache
  • Code Generation & Type Safety — Apollo iOS generates Swift types from GraphQL schemas at build time, eliminating JSON parsing and runtime type errors—the CLI is the bridge between GraphQL definitions and Swift code
  • Deferred Query Fragments — GraphQL @defer directive support (PossiblyDeferred.swift) allows incremental result streaming, useful for large responses or slow networks—non-obvious since it changes the result accumulation semantics
  • Auto-Persisted Queries (APQ) — AutoPersistedQueryConfiguration.swift enables sending query hashes instead of full query text to reduce bandwidth—important for mobile where data usage matters, non-obvious optimization
  • Cache Policy (Network-First, Cache-First, etc.) — CachePolicy.swift defines fetch strategy—returnCacheDataElseFetch, returnCacheDataAndFetch, networkOnly—these are subtle but critical for user experience (stale data vs. freshness)
  • Accumulator Pattern for Result Assembly — GraphQLResultAccumulator and DataDictMapper follow a visitor/builder pattern to construct type-safe results from normalized cache entries—tricky to modify without breaking type guarantees
  • apollographql/apollo-client — The JavaScript/TypeScript equivalent—same design philosophy and caching architecture but for web/Node.js, useful for understanding the reference implementation
  • apollographql/apollo-kotlin — The Android/Kotlin equivalent—shares normalized cache design and execution pipeline patterns with apollo-ios for consistent cross-platform behavior
  • apollographql/apollo-ios-dev — The development/CI repository where the code generation CLI and new features are actively developed—apollo-ios itself pulls the compiled CLI from here
  • apple/swift — The Swift language repository—needed to understand language features and standard library APIs that apollo-ios depends on, especially concurrency primitives
  • apollographql/graphql-core — The GraphQL reference implementation and spec—apollo-ios must conform to GraphQL spec for query execution, result normalization, and introspection

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for DataDict+Merging.swift

The file Sources/Apollo/DataDict+Merging.swift appears to handle critical data merging logic for the normalized cache, but there's no corresponding test file visible in the repository structure. This is a high-risk area for bugs since merging operations directly affect cache correctness. Adding thorough unit tests would improve reliability and serve as documentation for merge behavior.

  • [ ] Create Tests/ApolloTests/DataDictMergingTests.swift
  • [ ] Add tests for basic field merging scenarios (primitive types, nested objects)
  • [ ] Add tests for array merging with various conflict scenarios
  • [ ] Add tests for null handling and optional field merging
  • [ ] Add tests for nested DataDict merging with circular references
  • [ ] Add performance tests for large object graph merging

Add integration tests for AsyncReadWriteLock under concurrent load

The Sources/Apollo/Internal Utilities/AsyncReadWriteLock.swift is a critical synchronization primitive used throughout the caching system, but there are no visible dedicated tests for concurrent scenarios. Given its importance to cache thread-safety, this needs comprehensive concurrent testing beyond typical unit tests.

  • [ ] Create Tests/ApolloTests/AsyncReadWriteLockTests.swift
  • [ ] Add tests for concurrent read operations (verify multiple readers can proceed)
  • [ ] Add tests for write exclusivity (verify readers block during writes)
  • [ ] Add tests for reader-writer starvation scenarios
  • [ ] Add stress tests with high contention using Task groups
  • [ ] Add tests validizing fairness and ordering guarantees

Add GitHub Actions workflow for Swift Package Index (SPI) compatibility verification

The repo has a .spi.yml configuration file but no visible GitHub Actions workflow to verify Swift Package Index compatibility during CI. This ensures the package remains compatible with SPM across different platforms (iOS, macOS, watchOS, tvOS, visionOS) and Swift versions as mentioned in the README.

  • [ ] Create .github/workflows/spi-compatibility-check.yml
  • [ ] Add build step verifying package builds successfully on macOS with SPM
  • [ ] Add validation for all platform targets: iOS, macOS, watchOS, tvOS, visionOS
  • [ ] Test against multiple Swift versions (5.7, 5.8, 5.9+)
  • [ ] Verify documentation builds via docc (Sources/Apollo/Documentation.docc/)
  • [ ] Set up scheduled runs and PR validation triggers

🌿Good first issues

  • Add missing docstrings to Sources/Apollo/Execution/ExecutionSources/ (CacheDataExecutionSource.swift, NetworkResponseExecutionSource.swift, SelectionSetModelExecutionSource.swift)—each executor source should document when/why it's used and its side effects on cache state
  • Write integration tests for the caching layer in Sources/Apollo/Caching/—specifically test Record eviction, RecordSet merging, and CacheReference resolution with circular dependencies, which are not visible in the file list but are critical for production use
  • Complete the Documentation.docc/ site with code examples for Sources/Apollo/Execution/ResultAccumulators/DataDictMapper.swift showing how to customize result mapping behavior—currently this mapper is underdocumented for advanced users

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 38c2022 — Update CHANGELOG.md for v2.1.2 (AnthonyMDev)
  • 1e582bb — Setting up Release 2.1.2 (gh-action-runner)
  • 599c3c2 — Updated version numbers (gh-action-runner)
  • 586103d — fix: Make SubscriptionStream initializer public (#975) (AnthonyMDev)
  • 9bfa711 — docs: fix Apollo iOS README API Reference link, add AI Skill resource (#964) (AnthonyMDev)
  • de8d0a5 — chore(deps): update actions/add-to-project action to v2 (#963) (svc-secops)
  • a5f98b1 — Update CHANGELOG.md for v2.1.1 (AnthonyMDev)
  • 189934e — Setting up Release 2.1.1 (gh-action-runner)
  • ffde16d — Updated version numbers (gh-action-runner)
  • 059f998 — Remove cocoapods check (tahirmt)

🔒Security observations

Apollo iOS demonstrates generally good security practices with gitleaks configuration for secret scanning and organized code structure. Primary concerns are around supply chain integrity (git submodules, binary artifacts), lack of visible SBOM documentation, and the need for thorough security code review of network, caching, and file handling components. The codebase follows security-conscious patterns with clear separation of concerns (interceptors, caching, execution sources) which is positive. No critical vulnerabilities identified in the static file structure analysis, but runtime security and proper configuration of GraphQL client require careful implementation by users.

  • Medium · Potential Hardcoded Credentials in CLI Distribution — CLI/apollo-ios-cli.tar.gz. The presence of 'CLI/apollo-ios-cli.tar.gz' as a binary artifact in the repository could potentially contain hardcoded credentials, API keys, or sensitive configuration. Binary files in version control pose risks for credential exposure. Fix: Ensure binary artifacts are excluded from version control using .gitignore. Implement automated secret scanning using gitleaks (already configured but verify it scans all file types). Consider using git-lfs for binary management or moving artifacts to a separate artifact repository.
  • Low · Git Submodules Configured — .gitmodules. The presence of '.gitmodules' indicates the use of Git submodules. This can introduce supply chain risks if submodule repositories are compromised or if submodule pinning is not properly enforced. Fix: Verify all submodule sources are from trusted repositories. Ensure submodules are pinned to specific commit hashes rather than branches. Regularly audit submodule dependencies and implement automated updates with verification.
  • Low · Missing SBOM (Software Bill of Materials) — Package.swift (root dependency management). No evidence of SBOM generation or dependency manifest in the file structure. Apollo iOS is a widely-used dependency that should provide transparency about its own dependencies. Fix: Generate and maintain a Software Bill of Materials (SBOM) using tools like SPDX. Include detailed dependency information in releases. Consider implementing automated SBOM generation in CI/CD pipeline.
  • Low · No Evidence of CODEOWNERS Security Policy — .github/CODEOWNERS. While '.github/CODEOWNERS' file exists, its content is not visible. Verify that it includes security-critical components and that appropriate approval processes are in place. Fix: Ensure CODEOWNERS file includes all security-sensitive components (cache handling, network transport, interceptors). Require multiple approvals for security-related changes. Regularly audit and update CODEOWNERS.
  • Low · Potential Security-Relevant Code Patterns Require Review — Sources/Apollo/Caching/ApolloStore.swift, Sources/Apollo/RequestChain/Interceptors/HTTPInterceptor.swift, Sources/Apollo/MultipartFormData.swift. Multiple security-sensitive components are present: ApolloStore.swift (caching), HTTPInterceptor.swift (network), MultipartFormData.swift (file handling), and GraphQLHTTPRequestError.swift. These require careful security review to prevent information disclosure. Fix: Conduct security code review focusing on: 1) Cache invalidation and sensitive data handling in ApolloStore, 2) SSL/TLS certificate validation in HTTPInterceptor, 3) File upload validation and size limits in MultipartFormData, 4) Error messages do not leak sensitive information.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · apollographql/apollo-ios — RepoPilot