<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/56-60-days-system-design-questions-wphlukni9" -->

---
title: 56/60 Days System Design Questions | daily.dev
description: Long-running background jobs break assumptions built for synchronous APIs. Using a video upload scenario (2–8 minutes, millions of users), four client...
canonical: https://daily.dev/posts/56-60-days-system-design-questions-wphlukni9
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: 56/60 Days System Design Questions | daily.dev
og:description: Long-running background jobs break assumptions built for synchronous APIs. Using a video upload scenario (2–8 minutes, millions of users), four client...
og:url: https://daily.dev/posts/56-60-days-system-design-questions-wphlukni9
og:image: https://api.daily.dev/og/posts/wpHLUknI9.png
og:image:alt: 56/60 Days System Design Questions
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# 56/60 Days System Design Questions

**[Joud Awad](https://daily.dev/sources/iac4jsbu0lv8wbsc85fsh)** · [@joudawad](https://daily.dev/joudawad) · 2 min read · 152 upvotes · 27 comments

## Summary

Long-running background jobs break assumptions built for synchronous APIs. Using a video upload scenario (2–8 minutes, millions of users), four client notification strategies are compared: polling, webhooks, SSE/WebSocket, and synchronous wait. Beyond transport choice, four critical design problems are highlighted that teams typically get wrong: idempotency (safe retries), progress granularity (meaningful intermediate states), distinguishing timeout from failure (heartbeats/visibility timeouts), and deduplication (scoped dedup keys to prevent double-processing).

## Content

Your background job ran for 4 minutes and nobody knows if it finished.

That's not a job queue problem. That's a missing design problem.

Long-running jobs break every assumption you built for synchronous APIs. Your load balancer times out after 30s. Your mobile client doesn't know whether to retry. Your retry logic re-runs a job that already half-completed.

Here's the real scenario:

You're processing a video upload. The job takes 2–8 minutes. Millions of users.

What do you expose to the client?

**A) Polling endpoint — client hits **/jobs/:id/status** every 5s until done**

**B) Webhook — job fires a POST to client's callback URL on completion**

**C) SSE / WebSocket — server pushes progress updates in real time**

**D) Synchronous wait — keep the HTTP connection open until the job finishes**

One scales to millions without coupling your infrastructure to client uptime.

The others have hard production failure modes most teams don't discover until 3 AM.

The deeper problem isn't transport — it's these 4 things nobody gets right the first time:

→ **Idempotency.** Every job must be safe to re-run. If your retry logic can double-charge, double-send, or double-process — you don't have retries, you have bugs waiting.

→ **Progress granularity.** "0% → 100%" is useless for a 6-minute job. You need intermediate states: queued, processing, transcoding, uploading, complete. Clients need something to show users.

→ **Timeout vs failure.** A job that stops responding isn't the same as a job that failed. Dead workers, OOM kills, spot instance evictions — your queue needs a heartbeat or a visibility timeout, not just a try/catch.

→ **Deduplication.** The client will retry. Your queue will redeliver. You need a dedup key scoped to the original request — not the job run.

Pick one — A, B, C, or D — and tell me why. Full breakdown in the comments.

#30DaysOfSystemDesign #SystemDesign #BackendEngineering #DistributedSystems

## Community discussion

Top comments from developers on daily.dev.

**@joudawad** · 12 upvotes

> **A) Polling — Correct for most cases**
>
> Client-controlled, stateless, scales independently. The server doesn't care if the client disconnects, retries, or crashes — the job runs and the status endpoint just answers queries. 5s polling intervals on a job that takes 2–8 minutes is trivially cheap. The key rules: make job IDs stable and idempotent, set a TTL on job records so you don't accumulate state forever, and use exponential backoff not fixed intervals. LinkedIn, YouTube, and S3 multipart uploads all use polling for async job status.
>
>
> ![ChatGPT Image Jul 1, 2026, 07_23_37...

**@joudawad** · 9 upvotes

> **B) Webhook — Right idea, wrong default**
>
> Webhooks are great for server-to-server flows where the receiver has a stable HTTPS endpoint. They fall apart for mobile clients (no public URL), in environments with NAT/firewall, and when the receiver is down at delivery time. You'd need a retry queue, delivery guarantees, and signature verification just to make it reliable. Webhooks work well as a supplementary delivery mechanism for platform integrations — not as the primary client notification path for end users.

**@joudawad** · 9 upvotes

> **C) SSE / WebSocket — Expensive for this use case**
>
> Real-time push is fantastic for chat, live dashboards, and collaborative editing. For a job that takes 2–8 minutes and is triggered once? You're holding an open connection, burning a file descriptor, and adding connection-management complexity for maybe 3 meaningful state changes. SSE makes sense when you genuinely need sub-second updates or continuous streaming. For async job progress, polling is cheaper and simpler.

**@joudawad** · 7 upvotes

> **D) Synchronous wait — Production antipattern**
>
> Keeping the HTTP connection open for 2–8 minutes kills your load balancer (most timeout at 30–60s), ties up a server thread or process, and gives the client no recovery path if the connection drops mid-job. This is how systems get "stuck" — jobs complete but the client never hears about it because the connection dropped at minute 3. Never block on long-running work. Always return immediately with a job ID.

**@erikandersoon** · 3 upvotes

> **Answer: B) Webhook — job fires a POST to client's callback URL on completion**
>
> **Why B is the right choice for this scenario:**
>
> You're processing video uploads that take 2–8 minutes with millions of users. This is an _asynchronous_, _long-running_, _high-volume_ workload. The client shouldn't be holding a connection or waiting — it should fire-and-forget and get notified when the job is done.

---

Tags: [#backend](https://daily.dev/tags/backend), [#career](https://daily.dev/tags/career), [#distributed-systems](https://daily.dev/tags/distributed-systems)

[View this post on daily.dev](https://daily.dev/posts/56-60-days-system-design-questions-wphlukni9)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"DiscussionForumPosting","mainEntityOfPage":"https://daily.dev/posts/56-60-days-system-design-questions-wphlukni9","headline":"56/60 Days System Design Questions","text":"Long-running background jobs break assumptions built for synchronous APIs. Using a video upload scenario (2–8 minutes, millions of users), four client notification strategies are compared: polling, webhooks, SSE/WebSocket, and synchronous wait. Beyond transport choice, four critical design problems are highlighted that teams typically get wrong: idempotency (safe retries), progress granularity (meaningful intermediate states), distinguishing timeout from failure (heartbeats/visibility timeouts), and deduplication (scoped dedup keys to prevent double-processing).","url":"https://daily.dev/posts/56-60-days-system-design-questions-wphlukni9","datePublished":"2026-07-01T16:19:16.336Z","dateModified":"2026-07-16T02:12:54.028Z","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0","description":"Principal Solution Architecture ","worksFor":{"@type":"Organization","name":"Metalab","logo":"https://www.google.com/s2/favicons?domain=metalab.com&sz=128"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"EndorseAction"},"userInteractionCount":81870}},"image":"https://media.daily.dev/image/upload/s--oGArE-Ko--/f_auto/v1782922759/posts/wpHLUknI9?_a=BAMAMicg0","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":152},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":27}],"comment":[{"@type":"Comment","text":"A) Polling — Correct for most cases\nClient-controlled, stateless, scales independently. The server doesn’t care if the client disconnects, retries, or crashes — the job runs and the status endpoint just answers queries. 5s polling intervals on a job that takes 2–8 minutes is trivially cheap. The key rules: make job IDs stable and idempotent, set a TTL on job records so you don’t accumulate state forever, and use exponential backoff not fixed intervals. LinkedIn, YouTube, and S3 multipart uploads all use polling for async job status.","datePublished":"2026-07-01T16:23:51.255Z","url":"https://daily.dev/posts/wpHLUknI9#c-xnnpY1McM","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":12}},{"@type":"Comment","text":"B) Webhook — Right idea, wrong default\nWebhooks are great for server-to-server flows where the receiver has a stable HTTPS endpoint. They fall apart for mobile clients (no public URL), in environments with NAT/firewall, and when the receiver is down at delivery time. You’d need a retry queue, delivery guarantees, and signature verification just to make it reliable. Webhooks work well as a supplementary delivery mechanism for platform integrations — not as the primary client notification path for end users.","datePublished":"2026-07-01T16:23:56.492Z","url":"https://daily.dev/posts/wpHLUknI9#c-XhLoa20rp","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":9}},{"@type":"Comment","text":"C) SSE / WebSocket — Expensive for this use case\nReal-time push is fantastic for chat, live dashboards, and collaborative editing. For a job that takes 2–8 minutes and is triggered once? You’re holding an open connection, burning a file descriptor, and adding connection-management complexity for maybe 3 meaningful state changes. SSE makes sense when you genuinely need sub-second updates or continuous streaming. For async job progress, polling is cheaper and simpler.","datePublished":"2026-07-01T16:24:02.264Z","url":"https://daily.dev/posts/wpHLUknI9#c-8A0SU9sNN","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":9}},{"@type":"Comment","text":"D) Synchronous wait — Production antipattern\nKeeping the HTTP connection open for 2–8 minutes kills your load balancer (most timeout at 30–60s), ties up a server thread or process, and gives the client no recovery path if the connection drops mid-job. This is how systems get “stuck” — jobs complete but the client never hears about it because the connection dropped at minute 3. Never block on long-running work. Always return immediately with a job ID.","datePublished":"2026-07-01T16:24:08.501Z","url":"https://daily.dev/posts/wpHLUknI9#c-22ZSBYJS2","author":{"@type":"Person","name":"Joud Awad","url":"https://daily.dev/joudawad","image":"https://media.daily.dev/image/upload/s--dOB9RaXY--/f_auto/v1773320801/avatars/avatar_iaC4JsBU0lV8wBsc85fSh?_a=BAMAMiiu0"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":7}},{"@type":"Comment","text":"Answer: B) Webhook — job fires a POST to client’s callback URL on completion\nWhy B is the right choice for this scenario:\nYou’re processing video uploads that take 2–8 minutes with millions of users. This is an asynchronous, long-running, high-volume workload. The client shouldn’t be holding a connection or waiting — it should fire-and-forget and get notified when the job is done.","datePublished":"2026-07-04T12:46:48.162Z","dateModified":"2026-07-04T12:46:57.192Z","url":"https://daily.dev/posts/wpHLUknI9#c-JUNXAXcGK","author":{"@type":"Person","name":"Erik Andersoon","url":"https://daily.dev/erikandersoon","image":"https://lh3.googleusercontent.com/a/ACg8ocIjscYXslkLRHxEihtWWVgTFELNg4TVNJzpD0qugegOqLsZAw=s96-c"},"interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":3}}],"isPartOf":{"@type":"WebPage","url":"https://daily.dev/sources/iac4jsbu0lv8wbsc85fsh","name":"Joud Awad"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Joud Awad","item":"https://daily.dev/sources/iac4jsbu0lv8wbsc85fsh"},{"@type":"ListItem","position":3,"name":"56/60 Days System Design Questions"}]}
```

