{"type":"excalidraw","version":2,"source":"https://AwesomeSystemDesign.dev","elements":[{"angle":0,"strokeColor":"#6577aa","backgroundColor":"#eef1fc","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-1"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-1"}],"updated":0,"link":null,"locked":false,"id":"shape-0","type":"rectangle","seed":41,"x":16,"y":16,"width":288,"height":407.8,"customData":{"revealStep":1}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-1"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-1","type":"text","seed":114,"x":36,"y":34,"width":248,"height":371.8,"fontSize":22,"fontFamily":1,"text":"Client makes GET\n/feed/stream\nServer holds\nconnection open until\nnew post arrives\nor timeout (30s).\n\n+ Lower latency than\npolling\n+ Fewer empty\nresponses\n- Still one connection\nper client","originalText":"Client makes GET\n/feed/stream\nServer holds\nconnection open until\nnew post arrives\nor timeout (30s).\n\n+ Lower latency than\npolling\n+ Fewer empty\nresponses\n- Still one connection\nper client","textAlign":"left","verticalAlign":"middle","containerId":"shape-0","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":1}},{"angle":0,"strokeColor":"#6577aa","backgroundColor":"#eef1fc","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-2"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-3"}],"updated":0,"link":null,"locked":false,"id":"shape-2","type":"rectangle","seed":187,"x":16,"y":467.8,"width":288,"height":722.4,"customData":{"revealStep":2}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-2"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-3","type":"text","seed":260,"x":36,"y":485.8,"width":248,"height":686.4,"fontSize":22,"fontFamily":1,"text":"Client polls GET\n/feed/new?since={las\nt_post_id}\nevery 30 seconds.\n\nServer: check if new\nposts exist in feed\ncache\nsince last_post_id.\n\nIf yes: return count\n(\"3 new tweets\")\nUser taps to load\nthem.\n\n+ Simple, works at\nscale\n- 30s delay, many\nempty polls\n- 500M users polling\n= 16M req/sec\n(but most users\naren't actively\nwatching feed)","originalText":"Client polls GET\n/feed/new?since={las\nt_post_id}\nevery 30 seconds.\n\nServer: check if new\nposts exist in feed\ncache\nsince last_post_id.\n\nIf yes: return count\n(\"3 new tweets\")\nUser taps to load\nthem.\n\n+ Simple, works at\nscale\n- 30s delay, many\nempty polls\n- 500M users polling\n= 16M req/sec\n(but most users\naren't actively\nwatching feed)","textAlign":"left","verticalAlign":"middle","containerId":"shape-2","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":2}},{"angle":0,"strokeColor":"#6577aa","backgroundColor":"#eef1fc","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-3"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-5"}],"updated":0,"link":null,"locked":false,"id":"shape-4","type":"rectangle","seed":333,"x":16,"y":1234.2,"width":288,"height":322,"customData":{"revealStep":3}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-3"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-5","type":"text","seed":406,"x":36,"y":1252.2,"width":248,"height":286,"fontSize":22,"fontFamily":1,"text":"Full-duplex persistent\nconnection.\nServer pushes new\nposts in real-time.\n\n+ Lowest latency,\nbidirectional\n- Expensive at scale\n(millions of\nconnections)","originalText":"Full-duplex persistent\nconnection.\nServer pushes new\nposts in real-time.\n\n+ Lowest latency,\nbidirectional\n- Expensive at scale\n(millions of\nconnections)","textAlign":"left","verticalAlign":"middle","containerId":"shape-4","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":3}},{"angle":0,"strokeColor":"#6577aa","backgroundColor":"#eef1fc","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-4"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-7"}],"updated":0,"link":null,"locked":false,"id":"shape-6","type":"rectangle","seed":479,"x":16,"y":1600.2,"width":288,"height":493.6,"customData":{"revealStep":4}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-4"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-7","type":"text","seed":552,"x":36,"y":1618.2,"width":248,"height":457.6,"fontSize":22,"fontFamily":1,"text":"Client opens\npersistent HTTP\nconnection.\nServer pushes new\npost notifications as\nthey arrive.\n\n+ True push, low\nlatency\n+ Works over HTTP\n(no special protocol)\n- Unidirectional\n(server -> client only)\n- Connections\nconsume server\nresources","originalText":"Client opens\npersistent HTTP\nconnection.\nServer pushes new\npost notifications as\nthey arrive.\n\n+ True push, low\nlatency\n+ Works over HTTP\n(no special protocol)\n- Unidirectional\n(server -> client only)\n- Connections\nconsume server\nresources","textAlign":"left","verticalAlign":"middle","containerId":"shape-6","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":4}},{"angle":0,"strokeColor":"#6577aa","backgroundColor":"#eef1fc","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-5"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-9"}],"updated":0,"link":null,"locked":false,"id":"shape-8","type":"rectangle","seed":625,"x":16,"y":2137.8,"width":288,"height":1494.6000000000001,"customData":{"revealStep":5}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-5"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-9","type":"text","seed":698,"x":36,"y":2155.8,"width":248,"height":1458.6000000000001,"fontSize":22,"fontFamily":1,"text":"Real-Time Timeline\nUpdates\n\nProblem: User has\nfeed open. A followed\nuser posts.\nHow does the new\npost appear without\nmanual refresh?\n\nApproach 1: Polling\n(Simple)\n\nApproach 2: Long\nPolling\n\nApproach 3:\nServer-Sent Events\n(SSE)\n\nApproach 4:\nWebSocket (for power\nusers)\n\nTwitter's actual\napproach: Hybrid\n\n- Web: polling every\n30s + \"N new\ntweets\" banner\n- Mobile: push\nnotification for\nhigh-priority\ncontent (mentions,\nviral from close\nfriends)\n- Active sessions:\nSSE for timeline\nupdates\n- Background: no\nconnection, show\nstale on open\n\nOnly ~5% of users\nare actively viewing\nthe feed\nat any given moment.\nThe other 95% just\nneed\nfresh data on next\napp open.","originalText":"Real-Time Timeline\nUpdates\n\nProblem: User has\nfeed open. A followed\nuser posts.\nHow does the new\npost appear without\nmanual refresh?\n\nApproach 1: Polling\n(Simple)\n\nApproach 2: Long\nPolling\n\nApproach 3:\nServer-Sent Events\n(SSE)\n\nApproach 4:\nWebSocket (for power\nusers)\n\nTwitter's actual\napproach: Hybrid\n\n- Web: polling every\n30s + \"N new\ntweets\" banner\n- Mobile: push\nnotification for\nhigh-priority\ncontent (mentions,\nviral from close\nfriends)\n- Active sessions:\nSSE for timeline\nupdates\n- Background: no\nconnection, show\nstale on open\n\nOnly ~5% of users\nare actively viewing\nthe feed\nat any given moment.\nThe other 95% just\nneed\nfresh data on next\napp open.","textAlign":"left","verticalAlign":"middle","containerId":"shape-8","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":5}}],"appState":{"viewBackgroundColor":"#fbfbf8","gridSize":null},"files":{}}