0Pricing
Swift Academy · Lesson

Retry Logic and Background URLSession

Implementing exponential backoff and continuing downloads in the background.

Retry Logic and Background URLSession is a free Swift Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Retry?

Transient failures (timeouts, 503 Service Unavailable) are recoverable. Retry logic improves resilience without user intervention.

func fetch(retries: Int = 3) async throws -> Data {
  for attempt in 0..<retries {
    do {
      return try await URLSession.shared.data(from: url).0
    } catch {
      if attempt == retries - 1 { throw error }
    }
  }
  fatalError("unreachable")
}

Exponential Backoff

Wait increasingly longer between retries to avoid overwhelming a struggling server: 1s, 2s, 4s.

for attempt in 0..<maxRetries {
  do { return try await fetch() } catch {
    if attempt < maxRetries - 1 {
      try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(attempt))) * 1_000_000_000)
    } else { throw error }
  }
}

Jitter to Prevent Thundering Herd

Add random jitter to backoff delays so retrying clients don't all hit the server at the same time.

let baseDelay = pow(2.0, Double(attempt))
let jitter = Double.random(in: 0..<1)
let delay = (baseDelay + jitter) * 1_000_000_000
try await Task.sleep(nanoseconds: UInt64(delay))

Retryable vs Non-Retryable Errors

Only retry transient errors. Client errors (401, 400) should not be retried.

func isRetryable(_ error: Error) -> Bool {
  if let urlErr = error as? URLError {
    return urlErr.code == .timedOut || urlErr.code == .networkConnectionLost
  }
  if let netErr = error as? NetworkError, case .httpError(let code) = netErr {
    return code >= 500
  }
  return false
}

Background URLSession

A background session continues downloads even when your app is suspended or terminated.

let config = URLSessionConfiguration.background(withIdentifier: "com.myapp.background")
let session = URLSession(configuration: config, delegate: self, delegateQueue: nil)

URLSessionDelegate for Background

Implement URLSessionDelegate to receive completion callbacks when the app is relaunched after a background task finishes.

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
  let dest = documentsURL.appendingPathComponent("download.pdf")
  try? FileManager.default.moveItem(at: location, to: dest)
}

Background App Refresh Handler

In AppDelegate, save the background completion handler and call it when all tasks finish.

func application(_ app: UIApplication, handleEventsForBackgroundURLSession id: String, completionHandler: @escaping () -> Void) {
  backgroundCompletionHandler = completionHandler
}
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
  DispatchQueue.main.async { self.backgroundCompletionHandler?() }
}

Download Task with Background Session

Use downloadTask(with:) on a background session for resilient large file downloads.

let task = session.downloadTask(with: URL(string: "https://cdn.example.com/large.zip")!)
task.resume()

Upload Task in Background

Background sessions also support upload tasks that continue when the app is not running.

var request = URLRequest(url: uploadURL)
request.httpMethod = "POST"
let task = session.uploadTask(with: request, fromFile: localFileURL)
task.resume()

Monitoring Progress

Observe URLSessionTaskDelegate to track upload/download progress for UI updates.

func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
  let progress = Double(totalBytesSent) / Double(totalBytesExpectedToSend)
  DispatchQueue.main.async { self.uploadProgress = progress }
}

Combining Retry with Background

Use foreground retry for API calls and background sessions for long-running downloads/uploads.

// API calls: async/await + exponential backoff retry
// Large downloads: URLSessionConfiguration.background + delegate

Quick Check

What technique prevents retrying clients from all hitting the server at the same moment?

Lesson Recap

Implement retry with exponential backoff + jitter for transient errors. Only retry 5xx and timeout errors. Use URLSessionConfiguration.background with a delegate for downloads/uploads that must survive app suspension.

Frequently asked questions

Is the “Retry Logic and Background URLSession” lesson free?

Yes — the full text of “Retry Logic and Background URLSession” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.

What will I learn in “Retry Logic and Background URLSession”?

Implementing exponential backoff and continuing downloads in the background. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Swift Academy?

No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Retry Logic and Background URLSession” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Swift Academy lesson?

Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. URLSession data(from:) with async/await
  2. Codable: Encoding and Decoding JSON
  3. Error Handling and HTTP Status Codes
  4. Retry Logic and Background URLSession
← Back to Swift Academy