WWDC Quick Look đź’“ By SwiftGGTeam
What's new in URLSession

What's new in URLSession

Watch original video

Highlight

URLSession in 2025 introduces a new API that fuses request and decoding, native Privacy Pass integration, a built-in retry policy, and connection-level performance metrics.

Main Points

Anyone who has written an iOS networking layer knows the boilerplate: fire the request, check the HTTP status code, hand the Data to JSONDecoder, map errors, and only then reach the business logic. A project ends up with dozens of call sites repeating the same flow, and a single missed branch drops a whole class of exceptions. This has been URLSession’s long-running pain — async/await solved callback hell, but decoding and error handling stayed manual.

In 2025, URLSession pushes this chain into the framework itself. The developer declares the return type, URLSession fetches the data, checks the status, decodes, and throws, and business code receives the model object directly. Alongside this come native Private Access Token negotiation, an exponential-backoff retry policy, and connection-level metrics that cover TLS handshakes and DNS resolution. The shared direction of these updates is to move what used to live as a private implementation in every APIClient into the system.

Details

A typical use of the merged request-and-decode call looks like this. The caller supplies the type, and URLSession handles every step in between:

struct UserProfile: Codable {
    let id: String
    let name: String
}

let url = URL(string: "https://api.example.com/me")!
let profile: UserProfile = try await URLSession.shared.data(
    from: url,
    as: UserProfile.self
)

Key points:

  • data(from:as:) takes the target type as a parameter, so the caller declares its expectations in the signature.
  • The return value is a decoded UserProfile, removing the (Data, URLResponse) tuple and the JSONDecoder().decode(...) call.
  • HTTP error status codes are thrown from inside the framework, so a single try await covers both network-layer and decoding-layer exceptions.

The retry policy is now declared at the configuration layer, and every task created from that configuration shares the same behavior:

let config = URLSessionConfiguration.default
config.retryPolicy = .exponentialBackoff(
    maxRetries: 3,
    initialInterval: .seconds(1)
)
let session = URLSession(configuration: config)

Key points:

  • retryPolicy is set on URLSessionConfiguration, so every request in the session behaves the same way.
  • .exponentialBackoff is a system-provided policy type, so the developer no longer writes the wait and counter logic.
  • Centralizing retry at the configuration layer means switching strategies is a one-line change rather than a sweep of every call site.

Privacy Pass integration is transparent on the client. The developer only has to implement the verification endpoint on the server. URLSession negotiates the token automatically on eligible requests, and the server receives proof of “real device, real app” without any user identifier attached.

Takeaways

  • Unify retry logic across the project. Why it pays off: in most projects, retries are scattered across various APIClients with inconsistent code, which makes debugging hard. How to start: build a factory method that returns a URLSessionConfiguration, route every session through it, align the policy first, then tune the parameters.
  • Use the new API in new modules first. Why it pays off: data(from:as:) saves boilerplate, but a full migration of an old project costs more than it returns. How to start: agree that all new networking calls use the new API, let old code migrate as part of normal refactors, and skip a dedicated migration PR.
  • Schedule Privacy Pass for anti-abuse endpoints. Why it pays off: sign-in, sign-up, and payment endpoints have long been hit by scripts and fraud. The old answer was an in-house risk system; now the platform offers a device attestation that carries no user information. How to start: first check the cost of the verification endpoint with the server team. The client requires no changes, but the rollout should wait until the server is ready.
  • Wire metrics into the monitoring dashboard. Why it pays off: URLSessionTaskMetrics now exposes TLS handshake and DNS resolution timings, which are the key signals for long-tail mobile network issues. How to start: sample on internal debug builds first, confirm the data shape, then decide whether to ship it to the existing APM system.

Comments

GitHub Issues · utterances