[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"categories-en":3,"post:\u002Fpost\u002Fframework-vs-sdk-who-calls-whom":37},[4,11,17,24,30],{"id":5,"slug":6,"name":7,"colorHex":8,"iconName":9,"postCount":10},"0e2c1225-f78a-4c20-8c93-998ab9dc93b9","frontend","Frontend","#40484f",null,25,{"id":12,"slug":13,"name":14,"colorHex":15,"iconName":9,"postCount":16},"bc8df70e-b7fb-4d89-a80c-fd458d36d58c","code-development","Code & Development","#8b5cf6",23,{"id":18,"slug":19,"name":20,"colorHex":21,"iconName":22,"postCount":23},"550e8400-e29b-41d4-a716-446655440001","inteligencia-artificial","Artificial Intelligence","#6366f1","brain",14,{"id":25,"slug":26,"name":27,"colorHex":28,"iconName":9,"postCount":29},"ea63b69c-2eb4-4100-81f3-70ce52d33743","tech-news","Tech News","#e50606",4,{"id":31,"slug":32,"name":33,"colorHex":34,"iconName":35,"postCount":36},"550e8400-e29b-41d4-a716-446655440017","how-to-guides","How-To & Guides","#be123c","book-open",2,{"post":38,"related":1079,"translations":1148,"resolved":9},{"id":39,"slug":40,"title":41,"excerpt":42,"image":43,"featured":44,"groupId":45,"publishedAt":46,"readingTime":47,"views":48,"author":49,"category":51,"tags":52,"contentJson":65,"metaTitle":1076,"metaDescription":1077,"updatedAt":1078},"81f24e9a-fc6b-47d0-beb9-d00a6137ed99","framework-vs-sdk-who-calls-whom","Framework vs SDK: Who Calls Whom","Most developers memorize names, but few understand the mechanism. Here is the simple rule to tell a framework from an SDK and level up your debugging.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1787491947099-featured-ikba2e.jpg",true,"0ccb21eb-6459-40ed-8110-227836e9bb74","2026-08-23T13:15:25.439194+00:00",10,0,{"name":50,"avatar":9},"Genildo Souza",{"slug":13,"name":14,"color":15},[53,56,59,62],{"slug":54,"name":55},"javascript","JavaScript",{"slug":57,"name":58},"python","Python",{"slug":60,"name":61},"runtime","Runtime",{"slug":63,"name":64},"sdk","Sdk",{"type":66,"content":67},"doc",[68,76,99,112,118,125,132,138,144,150,156,162,168,176,183,189,195,201,213,219,226,233,239,295,301,308,314,320,330,340,350,356,363,369,375,381,387,393,399,406,412,419,426,432,438,444,547,553,559,565,875,881,887,893,899,906,912,918,924,934,944,954,960,966,972,976,985,991,993,1002,1003,1009,1068],{"type":69,"attrs":70,"content":72},"paragraph",{"id":71},"p_1",[73],{"text":74,"type":75},"Every week someone asks me some version of this:","text",{"type":77,"attrs":78,"content":80},"blockquote",{"id":79},"quote_24oy0te1",[81,87,93],{"type":69,"attrs":82,"content":84},{"id":83},"p_q1",[85],{"text":86,"type":75},"Is Express a framework or a library?",{"type":69,"attrs":88,"content":90},{"id":89},"p_q2",[91],{"text":92,"type":75},"Is the OpenAI SDK a framework?",{"type":69,"attrs":94,"content":96},{"id":95},"p_q3",[97],{"text":98,"type":75},"Should I learn frameworks or SDKs first?",{"type":69,"attrs":100,"content":102},{"id":101},"p_2",[103,105,110],{"text":104,"type":75},"It sounds like a beginner question, but the confusion sticks around well into year three of a career. And it is not for lack of studying — it is that almost nobody explains the ",{"text":106,"type":75,"marks":107},"mechanism",[108],{"type":109},"bold",{"text":111,"type":75}," behind either one. People memorize names instead.",{"type":69,"attrs":113,"content":115},{"id":114},"p_3",[116],{"text":117,"type":75},"Once you understand the mechanism, something useful happens: you read docs faster, debug with less guesswork, and pick tools without depending on a Twitter thread. Let us get into it.",{"type":119,"attrs":120,"content":122},"heading",{"id":121,"level":36},"h_start",[123],{"text":124,"type":75},"The starting point: who calls whom",{"type":126,"attrs":127},"imageFigure",{"id":128,"alt":129,"src":130,"caption":131},"fig_8iuas2q6","Three flows side by side — your code calling a library, a framework calling your code, an SDK reaching the outside world.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494551828-z2n98h.png","One question separates all three: who is calling whom?",{"type":69,"attrs":133,"content":135},{"id":134},"p_4",[136],{"text":137,"type":75},"Hold on to this sentence, because it settles about 80% of the confusion:",{"type":139,"attrs":140},"pullquote",{"id":141,"quote":142,"accent":143,"attribution":9},"pq_rule","You call the library. The framework calls you. The SDK talks to the outside world.","default",{"type":69,"attrs":145,"content":147},{"id":146},"p_5",[148],{"text":149,"type":75},"It sounds reductive. It is not. It is literally about your program''s flow of control — who is holding the steering wheel during execution.",{"type":119,"attrs":151,"content":153},{"id":152,"level":36},"h_lib",[154],{"text":155,"type":75},"Library: you are in charge",{"type":126,"attrs":157},{"id":158,"alt":159,"src":160,"caption":161},"fig_onuu62fw","Diagram of your code calling a library function and receiving the return value.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494617967-ul1i3g.png","You import it, you call it, execution returns to you. No \"action,\" no movement.",{"type":69,"attrs":163,"content":165},{"id":164},"p_6",[166],{"text":167,"type":75},"A library is a bag of ready-made functions. You import it, call it when you feel like it, and execution comes right back to you.",{"type":169,"attrs":170,"content":173},"codeBlock",{"id":171,"language":54,"highlighted":172},"code_fw78yocj","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> { format } \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'date-fns'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> today\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> format\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">new\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Date\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(), \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'MM\u002Fdd\u002Fyyyy'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">console.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">log\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(today); \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F your code is still driving\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[174],{"text":175,"type":75},"import { format } from 'date-fns';\n\nconst today = format(new Date(), 'MM\u002Fdd\u002Fyyyy');\nconsole.log(today); \u002F\u002F your code is still driving",{"type":169,"attrs":177,"content":180},{"id":178,"language":57,"highlighted":179},"code_ewf6n4t2","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> datetime \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> datetime\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">today \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> datetime.now().strftime(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">%\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">m\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F%\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">d\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F%\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Y\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">print\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(today)  \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># your code is still driving\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[181],{"text":182,"type":75},"from datetime import datetime\n\ntoday = datetime.now().strftime('%m\u002F%d\u002F%Y')\nprint(today)  # your code is still driving",{"type":69,"attrs":184,"content":186},{"id":185},"p_7",[187],{"text":188,"type":75},"You are the director. The library is the actor who steps in when you yell action. If you never call it, it does nothing.",{"type":119,"attrs":190,"content":192},{"id":191,"level":36},"h_fw",[193],{"text":194,"type":75},"Framework: it is in charge (and that is the whole point)",{"type":126,"attrs":196},{"id":197,"alt":198,"src":199,"caption":200},"fig_9cl8lsje","Your code at the center, surrounded by a framework ring with arrows pointing inward.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494653507-gj2e33.png","The Hollywood Principle in code: \"don't call us, we'll call you.\"",{"type":69,"attrs":202,"content":204},{"id":203},"p_8",[205,207,211],{"text":206,"type":75},"Here everything flips. With a framework, ",{"text":208,"type":75,"marks":209},"you do not call its code — it calls yours",[210],{"type":109},{"text":212,"type":75},".",{"type":69,"attrs":214,"content":216},{"id":215},"p_9",[217],{"text":218,"type":75},"This has a name: Inversion of Control (IoC), also known as the Hollywood Principle: do not call us, we will call you.",{"type":169,"attrs":220,"content":223},{"id":221,"language":54,"highlighted":222},"code_rw0illqo","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> express \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'express'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> app\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> express\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F You are NOT executing anything here.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F You are REGISTERING a function and saying:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F \"when a GET hits \u002Fusers, call this\"\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">app.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">get\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'\u002Fusers'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">req\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">res\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=>\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  res.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">json\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">([{ id: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, name: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'Ana'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> }]);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">app.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">listen\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">3000\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">); \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F from this line on, the framework is in control\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[224],{"text":225,"type":75},"import express from 'express';\nconst app = express();\n\n\u002F\u002F You are NOT executing anything here.\n\u002F\u002F You are REGISTERING a function and saying:\n\u002F\u002F \"when a GET hits \u002Fusers, call this\"\napp.get('\u002Fusers', (req, res) => {\n  res.json([{ id: 1, name: 'Ana' }]);\n});\n\napp.listen(3000); \u002F\u002F from this line on, the framework is in control",{"type":169,"attrs":227,"content":230},{"id":228,"language":57,"highlighted":229},"code_jfor86xl","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> fastapi \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> FastAPI\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">app \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> FastAPI()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># Same idea: the decorator registers your function with the framework.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># It decides when the function runs, not you.\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">@app.get\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">users\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">def\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> list_users\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">():\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> [{\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">id\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">1\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">name\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Ana\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}]\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[231],{"text":232,"type":75},"from fastapi import FastAPI\napp = FastAPI()\n\n# Same idea: the decorator registers your function with the framework.\n# It decides when the function runs, not you.\n@app.get(\"\u002Fusers\")\ndef list_users():\n    return [{\"id\": 1, \"name\": \"Ana\"}]",{"type":69,"attrs":234,"content":236},{"id":235},"p_10",[237],{"text":238,"type":75},"Notice what you did not write in either snippet:",{"type":240,"attrs":241,"content":243},"bulletList",{"id":242,"tight":44},"ul_1",[244,255,265,275,285],{"type":245,"attrs":246,"content":248},"listItem",{"id":247},"li_1",[249],{"type":69,"attrs":250,"content":252},{"id":251},"p_l1",[253],{"text":254,"type":75},"you did not open a TCP socket",{"type":245,"attrs":256,"content":258},{"id":257},"li_2",[259],{"type":69,"attrs":260,"content":262},{"id":261},"p_l2",[263],{"text":264,"type":75},"you did not parse raw HTTP text",{"type":245,"attrs":266,"content":268},{"id":267},"li_3",[269],{"type":69,"attrs":270,"content":272},{"id":271},"p_l3",[273],{"text":274,"type":75},"you did not build the response headers",{"type":245,"attrs":276,"content":278},{"id":277},"li_4",[279],{"type":69,"attrs":280,"content":282},{"id":281},"p_l4",[283],{"text":284,"type":75},"you did not write the infinite loop waiting for connections",{"type":245,"attrs":286,"content":288},{"id":287},"li_5",[289],{"type":69,"attrs":290,"content":292},{"id":291},"p_l5",[293],{"text":294,"type":75},"you did not handle concurrent requests",{"type":69,"attrs":296,"content":298},{"id":297},"p_11",[299],{"text":300,"type":75},"All of that exists and is running right now. It just lives inside the framework.",{"type":119,"attrs":302,"content":305},{"id":303,"level":304},"h_engine",3,[306],{"text":307,"type":75},"What a framework really does under the hood",{"type":126,"attrs":309},{"id":310,"alt":311,"src":312,"caption":313},"fig_dgh3vbhb","Circular three-stage diagram: register, bootstrap and execution loop.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494691733-rrtdeg.png","Register, bootstrap, execution loop — the three-beat skeleton every framework runs on.",{"type":69,"attrs":315,"content":317},{"id":316},"p_12",[318],{"text":319,"type":75},"Every framework — web, UI, testing, whatever — runs on the same three-beat skeleton.",{"type":69,"attrs":321,"content":323},{"id":322},"p_13",[324,328],{"text":325,"type":75,"marks":326},"1. Registration phase. ",[327],{"type":109},{"text":329,"type":75},"You declare your pieces: routes, components, middleware, jobs, test cases. The framework stores them in an internal structure. app.get(...) does not execute your function; it pushes a record onto a list.",{"type":69,"attrs":331,"content":333},{"id":332},"p_14",[334,338],{"text":335,"type":75,"marks":336},"2. Bootstrap phase. ",[337],{"type":109},{"text":339,"type":75},"You hand over control (app.listen(), uvicorn main:app, npm test). The framework assembles what it needs: server, dependency injection, connections, component tree.",{"type":69,"attrs":341,"content":343},{"id":342},"p_15",[344,348],{"text":345,"type":75,"marks":346},"3. Execution loop. ",[347],{"type":109},{"text":349,"type":75},"The framework runs forever, listening for events. When one arrives, it consults that list from step 1, finds your function, and calls it — handing you pre-chewed data (req, res, props, event).",{"type":69,"attrs":351,"content":353},{"id":352},"p_16",[354],{"text":355,"type":75},"Here is crude pseudocode of what Express is doing while you sleep:",{"type":169,"attrs":357,"content":360},{"id":358,"language":54,"highlighted":359},"code_k5g7rn2f","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F this is the framework, not your code\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">while\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">true\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">) {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> rawRequest\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> socket.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">acceptConnection\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> req\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> parseHttp\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(rawRequest);            \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F becomes an object\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> route\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> routingTable.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">find\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(req.method, req.url);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">!\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">route) \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> respond404\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">();\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  for\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> (\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> middleware\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> of\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> middlewares) {       \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F lifecycle\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> middleware\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(req, res);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  }\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">  await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> route.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">handler\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(req, res);                \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">\u002F\u002F &#x3C;- YOUR code, at last\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">}\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[361],{"text":362,"type":75},"\u002F\u002F this is the framework, not your code\nwhile (true) {\n  const rawRequest = await socket.acceptConnection();\n  const req = parseHttp(rawRequest);            \u002F\u002F becomes an object\n  const route = routingTable.find(req.method, req.url);\n\n  if (!route) return respond404();\n\n  for (const middleware of middlewares) {       \u002F\u002F lifecycle\n    await middleware(req, res);\n  }\n\n  await route.handler(req, res);                \u002F\u002F \u003C- YOUR code, at last\n}",{"type":69,"attrs":364,"content":366},{"id":365},"p_17",[367],{"text":368,"type":75},"This is why frameworks have a lifecycle (useEffect, beforeEach, middleware, onMount). Those are hooks the framework offers so you can inject code at specific moments of the loop it controls. You do not get to choose when your code runs — only where it hangs.",{"type":69,"attrs":370,"content":372},{"id":371},"p_18",[373],{"text":374,"type":75},"It is also why frameworks are opinionated. By letting one drive, you accept its folder structure, its naming, its way of doing things. In exchange you get speed, and you do not rewrite HTTP parsing for the thousandth time in the history of computing.",{"type":119,"attrs":376,"content":378},{"id":377,"level":36},"h_sdk",[379],{"text":380,"type":75},"SDK: the translator between your code and someone else''s system",{"type":126,"attrs":382},{"id":383,"alt":384,"src":385,"caption":386},"fig_gfjmo4q5"," Your code connecting through an SDK block to a third-party service cloud.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494731830-t76cby.png","A translator between your application and a distant system, so you never speak raw HTTP.",{"type":69,"attrs":388,"content":390},{"id":389},"p_19",[391],{"text":392,"type":75},"SDK stands for Software Development Kit. In practice, today, nearly every SDK is the same thing: a package that wraps a service''s API so you do not have to speak raw HTTP.",{"type":69,"attrs":394,"content":396},{"id":395},"p_20",[397],{"text":398,"type":75},"Without an SDK, integrating with a service looks like this:",{"type":169,"attrs":400,"content":403},{"id":401,"language":57,"highlighted":402},"code_55v5da7a","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> uuid\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> requests\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">response \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> requests.post(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">    \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">https:\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">api.example.com\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">v1\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">charges\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">    headers\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">{\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">        \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Authorization\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">f\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Bearer {api_key}\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">        \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Content\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Type\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">application\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">json\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">        \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Idempotency\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">-\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">Key\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">str\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(uuid.uuid4()),\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    },\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">    json\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">{\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">amount\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">5000\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">, \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">currency\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">usd\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">},\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">    timeout\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">30\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> response.status_code \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">==\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 429\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">    ...\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # now what? backoff? how many retries?\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">if\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> response.status_code \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">>=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> 500\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">:\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">    ...\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\">  # retry? did the charge already go through?\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">data \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> response.json()  \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># untyped dict, no autocomplete\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[404],{"text":405,"type":75},"import uuid\nimport requests\n\nresponse = requests.post(\n    \"https:\u002F\u002Fapi.example.com\u002Fv1\u002Fcharges\",\n    headers={\n        \"Authorization\": f\"Bearer {api_key}\",\n        \"Content-Type\": \"application\u002Fjson\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json={\"amount\": 5000, \"currency\": \"usd\"},\n    timeout=30,\n)\n\nif response.status_code == 429:\n    ...  # now what? backoff? how many retries?\nif response.status_code >= 500:\n    ...  # retry? did the charge already go through?\n\ndata = response.json()  # untyped dict, no autocomplete",{"type":69,"attrs":407,"content":409},{"id":408},"p_21",[410],{"text":411,"type":75},"With an SDK:",{"type":169,"attrs":413,"content":416},{"id":414,"language":57,"highlighted":415},"code_su5sc0ds","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> stripe \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> StripeClient\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">client \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> StripeClient(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">api_key\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">api_key)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">charge \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> client.payment_intents.create({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">    \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">amount\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">5000\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">    \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">currency\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">usd\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">})\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">print\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(charge.id)\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[417],{"text":418,"type":75},"from stripe import StripeClient\n\nclient = StripeClient(api_key=api_key)\ncharge = client.payment_intents.create({\n    \"amount\": 5000,\n    \"currency\": \"usd\",\n})\nprint(charge.id)",{"type":169,"attrs":420,"content":423},{"id":421,"language":54,"highlighted":422},"code_00yw47s6","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> Stripe \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\"> 'stripe'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">;\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> stripe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> new\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> Stripe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(process.env.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">STRIPE_SECRET_KEY\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">);\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">const\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\"> charge\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> =\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\"> await\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> stripe.paymentIntents.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">create\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">({\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  amount: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">5000\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">  currency: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">'usd'\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">});\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">console.\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">log\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(charge.id);\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[424],{"text":425,"type":75},"import Stripe from 'stripe';\n\nconst stripe = new Stripe(process.env.STRIPE_SECRET_KEY);\nconst charge = await stripe.paymentIntents.create({\n  amount: 5000,\n  currency: 'usd',\n});\nconsole.log(charge.id);",{"type":69,"attrs":427,"content":429},{"id":428},"p_22",[430],{"text":431,"type":75},"Three header lines and all the error handling vanished. But they did not stop existing — they just moved.",{"type":119,"attrs":433,"content":435},{"id":434,"level":304},"h_sdk_does",[436],{"text":437,"type":75},"What a serious SDK handles for you",{"type":126,"attrs":439},{"id":440,"alt":441,"src":442,"caption":443},"fig_gbowig76","Six icons with labels for the work an SDK handles on your behalf.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494769941-pdzgeg.png","Auth, retries, idempotency, pagination, typed errors. Boring code someone already battle-tested.",{"type":240,"attrs":445,"content":448},{"id":446,"tight":447},"ul_2",false,[449,463,477,491,505,519,533],{"type":245,"attrs":450,"content":452},{"id":451},"li_s1",[453],{"type":69,"attrs":454,"content":456},{"id":455},"p_s1",[457,461],{"text":458,"type":75,"marks":459},"Authentication.",[460],{"type":109},{"text":462,"type":75}," Builds the header, refreshes expired tokens, reads the environment variable.",{"type":245,"attrs":464,"content":466},{"id":465},"li_s2",[467],{"type":69,"attrs":468,"content":470},{"id":469},"p_s2",[471,475],{"text":472,"type":75,"marks":473},"Serialization.",[474],{"type":109},{"text":476,"type":75}," Turns objects into JSON and JSON back into typed objects. You get autocomplete, which is underrated until you lose it.",{"type":245,"attrs":478,"content":480},{"id":479},"li_s3",[481],{"type":69,"attrs":482,"content":484},{"id":483},"p_s3",[485,489],{"text":486,"type":75,"marks":487},"Retry with exponential backoff.",[488],{"type":109},{"text":490,"type":75}," Got a 429 or a 503? Once you enable it, the client retries quickly on the first failure and then on an exponential backoff schedule, instead of giving up. Note it is opt-in: Stripe ships the mechanism, you configure it.",{"type":245,"attrs":492,"content":494},{"id":493},"li_s4",[495],{"type":69,"attrs":496,"content":498},{"id":497},"p_s4",[499,503],{"text":500,"type":75,"marks":501},"Idempotency.",[502],{"type":109},{"text":504,"type":75}," Generates a unique key so a retry does not charge your customer twice — Stripe stores that key for 24 hours and replays the original result. This one item alone pays for the SDK.",{"type":245,"attrs":506,"content":508},{"id":507},"li_s5",[509],{"type":69,"attrs":510,"content":512},{"id":511},"p_s5",[513,517],{"text":514,"type":75,"marks":515},"Pagination.",[516],{"type":109},{"text":518,"type":75}," Turns cursor juggling into a plain iterator.",{"type":245,"attrs":520,"content":522},{"id":521},"li_s6",[523],{"type":69,"attrs":524,"content":526},{"id":525},"p_s6",[527,531],{"text":528,"type":75,"marks":529},"Typed errors.",[530],{"type":109},{"text":532,"type":75}," RateLimitError, AuthenticationError — instead of comparing loose status numbers.",{"type":245,"attrs":534,"content":536},{"id":535},"li_s7",[537],{"type":69,"attrs":538,"content":540},{"id":539},"p_s7",[541,545],{"text":542,"type":75,"marks":543},"Versioning.",[544],{"type":109},{"text":546,"type":75}," Pins the remote API version so the server does not shift under your feet.",{"type":69,"attrs":548,"content":550},{"id":549},"p_23",[551],{"text":552,"type":75},"None of this is magic. It is boring, tedious, edge-case-riddled code that somebody already wrote, battle-tested in production, and maintains for you. That is the SDK.",{"type":119,"attrs":554,"content":556},{"id":555,"level":36},"h_table",[557],{"text":558,"type":75},"The table worth taping to your monitor",{"type":126,"attrs":560},{"id":561,"alt":562,"src":563,"caption":564},"fig_zy9wryao","Table comparing library, framework and SDK across seven traits.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494797660-bc4tqs.png","The row that matters most is the highlighted one: cost to switch.",{"type":566,"attrs":567,"content":569},"table",{"id":568},"tbl_1",[570,611,649,686,724,761,799,837],{"type":571,"content":572},"tableRow",[573,584,593,602],{"type":574,"attrs":575,"content":577},"tableHeader",{"align":9,"colspan":576,"rowspan":576,"colwidth":9},1,[578],{"type":69,"attrs":579,"content":581},{"id":580},"p_hk6so8eq",[582],{"text":583,"type":75},"Trait",{"type":574,"attrs":585,"content":586},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[587],{"type":69,"attrs":588,"content":590},{"id":589},"p_25p3uoao",[591],{"text":592,"type":75},"Library",{"type":574,"attrs":594,"content":595},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[596],{"type":69,"attrs":597,"content":599},{"id":598},"p_yncx1qw4",[600],{"text":601,"type":75},"Framework",{"type":574,"attrs":603,"content":604},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[605],{"type":69,"attrs":606,"content":608},{"id":607},"p_4asrd1qe",[609],{"text":610,"type":75},"SDK",{"type":571,"content":612},[613,623,632,641],{"type":614,"attrs":615,"content":616},"tableCell",{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[617],{"type":69,"attrs":618,"content":620},{"id":619},"p_dg5mnrl7",[621],{"text":622,"type":75},"Who calls whom",{"type":614,"attrs":624,"content":625},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[626],{"type":69,"attrs":627,"content":629},{"id":628},"p_waceu3y3",[630],{"text":631,"type":75},"you call it",{"type":614,"attrs":633,"content":634},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[635],{"type":69,"attrs":636,"content":638},{"id":637},"p_xmnbdsw4",[639],{"text":640,"type":75},"it calls you",{"type":614,"attrs":642,"content":643},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[644],{"type":69,"attrs":645,"content":647},{"id":646},"p_pkt9utt7",[648],{"text":631,"type":75},{"type":571,"content":650},[651,660,669,678],{"type":614,"attrs":652,"content":653},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[654],{"type":69,"attrs":655,"content":657},{"id":656},"p_2s5wys44",[658],{"text":659,"type":75},"Flow of control",{"type":614,"attrs":661,"content":662},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[663],{"type":69,"attrs":664,"content":666},{"id":665},"p_uui56ylr",[667],{"text":668,"type":75},"yours",{"type":614,"attrs":670,"content":671},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[672],{"type":69,"attrs":673,"content":675},{"id":674},"p_eo0twccs",[676],{"text":677,"type":75},"its",{"type":614,"attrs":679,"content":680},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[681],{"type":69,"attrs":682,"content":684},{"id":683},"p_6uc9pcgg",[685],{"text":668,"type":75},{"type":571,"content":687},[688,697,706,715],{"type":614,"attrs":689,"content":690},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[691],{"type":69,"attrs":692,"content":694},{"id":693},"p_8ag7mz7a",[695],{"text":696,"type":75},"Problem it solves",{"type":614,"attrs":698,"content":699},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[700],{"type":69,"attrs":701,"content":703},{"id":702},"p_6xclkpgd",[704],{"text":705,"type":75},"one specific task",{"type":614,"attrs":707,"content":708},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[709],{"type":69,"attrs":710,"content":712},{"id":711},"p_x6uh9v52",[713],{"text":714,"type":75},"your app structure",{"type":614,"attrs":716,"content":717},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[718],{"type":69,"attrs":719,"content":721},{"id":720},"p_hj74l74e",[722],{"text":723,"type":75},"talking to an external system",{"type":571,"content":725},[726,735,744,752],{"type":614,"attrs":727,"content":728},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[729],{"type":69,"attrs":730,"content":732},{"id":731},"p_k9cwhto3",[733],{"text":734,"type":75},"Where the work runs",{"type":614,"attrs":736,"content":737},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[738],{"type":69,"attrs":739,"content":741},{"id":740},"p_q18mhlkl",[742],{"text":743,"type":75},"your machine",{"type":614,"attrs":745,"content":746},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[747],{"type":69,"attrs":748,"content":750},{"id":749},"p_y9t6d98g",[751],{"text":743,"type":75},{"type":614,"attrs":753,"content":754},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[755],{"type":69,"attrs":756,"content":758},{"id":757},"p_patzn7lv",[759],{"text":760,"type":75},"someone else''s server",{"type":571,"content":762},[763,772,781,790],{"type":614,"attrs":764,"content":765},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[766],{"type":69,"attrs":767,"content":769},{"id":768},"p_u15k31ef",[770],{"text":771,"type":75},"How many per project",{"type":614,"attrs":773,"content":774},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[775],{"type":69,"attrs":776,"content":778},{"id":777},"p_nfc4eyse",[779],{"text":780,"type":75},"dozens",{"type":614,"attrs":782,"content":783},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[784],{"type":69,"attrs":785,"content":787},{"id":786},"p_dy7si49u",[788],{"text":789,"type":75},"1 (rarely 2)",{"type":614,"attrs":791,"content":792},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[793],{"type":69,"attrs":794,"content":796},{"id":795},"p_spmvw8t8",[797],{"text":798,"type":75},"one per service",{"type":571,"content":800},[801,810,819,828],{"type":614,"attrs":802,"content":803},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[804],{"type":69,"attrs":805,"content":807},{"id":806},"p_oymiel6v",[808],{"text":809,"type":75},"Cost of switching",{"type":614,"attrs":811,"content":812},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[813],{"type":69,"attrs":814,"content":816},{"id":815},"p_m7hipz07",[817],{"text":818,"type":75},"low",{"type":614,"attrs":820,"content":821},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[822],{"type":69,"attrs":823,"content":825},{"id":824},"p_9k38axob",[826],{"text":827,"type":75},"brutal (rewrite)",{"type":614,"attrs":829,"content":830},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[831],{"type":69,"attrs":832,"content":834},{"id":833},"p_oe3tq0hl",[835],{"text":836,"type":75},"medium",{"type":571,"content":838},[839,848,857,866],{"type":614,"attrs":840,"content":841},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[842],{"type":69,"attrs":843,"content":845},{"id":844},"p_imeo2o59",[846],{"text":847,"type":75},"Examples",{"type":614,"attrs":849,"content":850},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[851],{"type":69,"attrs":852,"content":854},{"id":853},"p_5mh8kf90",[855],{"text":856,"type":75},"lodash, date-fns, pandas",{"type":614,"attrs":858,"content":859},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[860],{"type":69,"attrs":861,"content":863},{"id":862},"p_yw6szxe6",[864],{"text":865,"type":75},"React, Django, Rails, Spring",{"type":614,"attrs":867,"content":868},{"align":9,"colspan":576,"rowspan":576,"colwidth":9},[869],{"type":69,"attrs":870,"content":872},{"id":871},"p_mm2vfi2d",[873],{"text":874,"type":75},"Stripe, AWS boto3, OpenAI",{"type":69,"attrs":876,"content":878},{"id":877},"p_24",[879],{"text":880,"type":75},"The most practical row is the cost of switching. Swapping date-fns for day.js is an afternoon. Swapping Django for FastAPI is a quarter. That is why framework choices deserve a meeting and library choices do not.",{"type":119,"attrs":882,"content":884},{"id":883,"level":36},"h_real",[885],{"text":886,"type":75},"In real life, all three live in the same file",{"type":126,"attrs":888},{"id":889,"alt":890,"src":891,"caption":892},"fig_taoyzx8v","Code snippet with three annotations pointing at the framework, the SDK and the library.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494828117-dwkmek.png","Four lines, three roles. The framework is the stage, the SDK is the phone, the library is the workbench tool.",{"type":69,"attrs":894,"content":896},{"id":895},"p_25",[897],{"text":898,"type":75},"And there is nothing wrong with that:",{"type":169,"attrs":900,"content":903},{"id":901,"language":57,"highlighted":902},"code_2b80n5en","\u003Cpre class=\"shiki shiki-themes github-light github-dark\" style=\"--shiki-light:#24292e;--shiki-dark:#e1e4e8;--shiki-light-bg:#fff;--shiki-dark-bg:#24292e\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> os\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> fastapi \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> FastAPI          \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># framework: runs the application\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> stripe \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> StripeClient      \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># SDK: talks to Stripe\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">from\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> datetime \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">import\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> datetime        \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># library: one specific task\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">app \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> FastAPI()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">stripe \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> StripeClient(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#E36209;--shiki-dark:#FFAB70\">api_key\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">os.environ[\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">STRIPE_KEY\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">])\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\">@app.post\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">\u002F\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">subscribe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">)                       \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># the FRAMEWORK will call this\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">def\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6F42C1;--shiki-dark:#B392F0\"> subscribe\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">(amount: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">int\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">):\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    charge \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">=\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> stripe.payment_intents.create({  \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># YOU call the SDK\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">        \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">amount\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: amount,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">        \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">currency\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">usd\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    })\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#D73A49;--shiki-dark:#F97583\">    return\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\"> {\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">        \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#005CC5;--shiki-dark:#79B8FF\">id\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: charge.id,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">        \"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">created_at\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#032F62;--shiki-dark:#9ECBFF\">\"\u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">: datetime.now().isoformat(),  \u003C\u002Fspan>\u003Cspan style=\"--shiki-light:#6A737D;--shiki-dark:#6A737D\"># YOU call the library\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"--shiki-light:#24292E;--shiki-dark:#E1E4E8\">    }\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",[904],{"text":905,"type":75},"import os\n\nfrom fastapi import FastAPI          # framework: runs the application\nfrom stripe import StripeClient      # SDK: talks to Stripe\nfrom datetime import datetime        # library: one specific task\n\napp = FastAPI()\nstripe = StripeClient(api_key=os.environ[\"STRIPE_KEY\"])\n\n@app.post(\"\u002Fsubscribe\")                       # the FRAMEWORK will call this\ndef subscribe(amount: int):\n    charge = stripe.payment_intents.create({  # YOU call the SDK\n        \"amount\": amount,\n        \"currency\": \"usd\",\n    })\n    return {\n        \"id\": charge.id,\n        \"created_at\": datetime.now().isoformat(),  # YOU call the library\n    }",{"type":69,"attrs":907,"content":909},{"id":908},"p_26",[910],{"text":911,"type":75},"Three import lines, three different roles. The framework is the stage. The SDK is the phone. The library is the tool on the workbench.",{"type":119,"attrs":913,"content":915},{"id":914,"level":36},"h_head",[916],{"text":917,"type":75},"What changes in your head after this",{"type":126,"attrs":919},{"id":920,"alt":921,"src":922,"caption":923},"fig_k6jovgfk","Two diagnostics side by side — a stack trace under a magnifier, and a network timeline under another.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494856011-0idalf.png","Framework error? Look inward. SDK error? Look outward.",{"type":69,"attrs":925,"content":927},{"id":926},"p_27",[928,932],{"text":929,"type":75,"marks":930},"You debug better. ",[931],{"type":109},{"text":933,"type":75},"A bug in framework code is almost never the framework''s fault — it is you using a hook at the wrong moment of the lifecycle. A bug in SDK code is almost always network, credentials, or rate limits. Knowing that cuts your investigation time in half.",{"type":69,"attrs":935,"content":937},{"id":936},"p_28",[938,942],{"text":939,"type":75,"marks":940},"You read docs in the right order. ",[941],{"type":109},{"text":943,"type":75},"Framework docs: start with the lifecycle and the folder structure. SDK docs: start with auth and the error codes. Library docs: go straight to the function signature.",{"type":69,"attrs":945,"content":947},{"id":946},"p_29",[948,952],{"text":949,"type":75,"marks":950},"You choose with actual criteria. ",[951],{"type":109},{"text":953,"type":75},"A framework is a marriage — check the community, the maintenance, the release cadence. An SDK is a vendor — prefer the official one, verify it has retries built in, and see how long since the last commit.",{"type":119,"attrs":955,"content":957},{"id":956,"level":36},"h_rule",[958],{"text":959,"type":75},"The rule of thumb",{"type":126,"attrs":961},{"id":962,"alt":963,"src":964,"caption":965},"fig_o7vfvh3t","Decision tree leading from \"does my code call this?\" to framework, library or SDK.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002F1787494883871-xjydx0.png","Facing any unfamiliar package, just walk this path.",{"type":69,"attrs":967,"content":969},{"id":968},"p_30",[970],{"text":971,"type":75},"Facing any unfamiliar package, ask one question:",{"type":139,"attrs":973},{"id":974,"quote":975,"accent":143,"attribution":9},"pq_final","Does my code call this, or will this call my code?",{"type":977,"attrs":978},"summaryBox",{"id":979,"items":980,"title":984},"sum_1",[981,982,983],"You call it and the work happens on your machine — library.","You call it and the work happens on another company''s server — SDK.","It calls you and dictates your project structure — framework.","The three answers:",{"type":69,"attrs":986,"content":988},{"id":987},"p_31",[989],{"text":990,"type":75},"That is it. Nothing else to memorize.",{"type":992},"horizontalRule",{"type":69,"attrs":994,"content":996},{"id":995},"p_32",[997],{"text":998,"type":75,"marks":999},"If this was useful, the natural next step is to open the source of whatever framework you use most and go find the main loop. Seeing with your own eyes the exact moment it calls your function is one of those things you cannot unsee — and it is what separates people who use tools from people who understand them.",[1000],{"type":1001},"italic",{"type":992},{"type":119,"attrs":1004,"content":1006},{"id":1005,"level":36},"h_sources",[1007],{"text":1008,"type":75},"Sources",{"type":240,"attrs":1010,"content":1012},{"id":1011,"tight":447},"ul_src",[1013,1034,1051],{"type":245,"attrs":1014,"content":1016},{"id":1015},"li_src1",[1017],{"type":69,"attrs":1018,"content":1020},{"id":1019},"p_src1",[1021,1032],{"text":1022,"type":75,"marks":1023},"Inversion of Control — Martin Fowler",[1024,1031],{"type":1025,"attrs":1026},"link",{"rel":1027,"href":1028,"class":1029,"title":9,"target":1030},"noopener noreferrer nofollow","https:\u002F\u002Fmartinfowler.com\u002Fbliki\u002FInversionOfControl.html","text-cyan-400 hover:underline cursor-pointer","_blank",{"type":109},{"text":1033,"type":75}," — the canonical definition. Fowler puts it plainly: the control is inverted, it calls me rather than me calling the framework. Also where the Hollywood Principle is tied to the concept.",{"type":245,"attrs":1035,"content":1037},{"id":1036},"li_src2",[1038],{"type":69,"attrs":1039,"content":1041},{"id":1040},"p_src2",[1042,1049],{"text":1043,"type":75,"marks":1044},"Idempotent requests — Stripe API Reference",[1045,1048],{"type":1025,"attrs":1046},{"rel":1027,"href":1047,"class":1029,"title":9,"target":1030},"https:\u002F\u002Fdocs.stripe.com\u002Fapi\u002Fidempotent_requests",{"type":109},{"text":1050,"type":75}," — official documentation on idempotency keys: V4 UUIDs recommended, up to 255 characters, pruned after 24 hours.",{"type":245,"attrs":1052,"content":1054},{"id":1053},"li_src3",[1055],{"type":69,"attrs":1056,"content":1058},{"id":1057},"p_src3",[1059,1066],{"text":1060,"type":75,"marks":1061},"Advanced error handling — Stripe Documentation",[1062,1065],{"type":1025,"attrs":1063},{"rel":1027,"href":1064,"class":1029,"title":9,"target":1030},"https:\u002F\u002Fdocs.stripe.com\u002Ferror-low-level",{"type":109},{"text":1067,"type":75}," — how the official libraries retry: first attempt quickly, then exponential backoff, respecting the Stripe-Should-Retry header. Confirms retries are opt-in and must be configured.",{"type":69,"attrs":1069,"content":1071},{"id":1070},"p_johnson",[1072],{"text":1073,"type":75,"marks":1074},"The framework definition Fowler cites comes from Ralph Johnson and Brian Foote: the methods defined by the user to tailor the framework will often be called from within the framework itself, rather than from the user''s application code. That sentence is from 1988 — the idea in this article is older than most of the tools it uses as examples.",[1075],{"type":1001},"Framework vs SDK vs Library: Who Calls Whom?","Stop guessing how your code runs. Learn the simple control-flow rule that distinguishes frameworks, SDKs, and libraries using JS and Python examples.","2026-08-24T19:48:21.134936+00:00",[1080,1100,1114,1130],{"id":1081,"slug":1082,"title":1083,"excerpt":1084,"image":1085,"featured":447,"groupId":1086,"publishedAt":1087,"readingTime":1088,"views":1089,"author":1090,"category":1091,"tags":1092},"c2d6b1ca-29bf-401f-8ab9-a1f828504d0b","microfrontends-with-angular-and-nx-what-nobody-tells-you","Microfrontends with Angular and Nx: what nobody tells you","Every tutorial teaches how to set up microfrontends in minutes, but few reveal the architectural chaos that emerges after months of production deploys.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1785206853570-featured-zoyhgn.webp","3368e1b2-b6de-4e94-a3d4-294fae8ade13","2026-08-03T01:42:48.969355+00:00",15,5,{"name":50,"avatar":9},{"slug":13,"name":14,"color":15},[1093,1096,1097],{"slug":1094,"name":1095},"angular","Angular",{"slug":54,"name":55},{"slug":1098,"name":1099},"typescript","TypeScript",{"id":1101,"slug":1102,"title":1103,"excerpt":1104,"image":1105,"featured":447,"groupId":1106,"publishedAt":1107,"readingTime":1108,"views":47,"author":1109,"category":1110,"tags":1111},"36440333-311c-4081-92e6-030a04a38fed","astro-island-architecture-performance-and-where-the-framework-truly-fits","Astro: Island Architecture, Performance, and Where the Framework Truly Fits","Astro challenges the modern web status quo by prioritizing static HTML and isolating interactivity into independent, lightweight code islands.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1785721161920-featured-a5vzkb.webp","cb62459e-7ace-43d3-a545-661c5695e925","2026-08-03T01:00:45.280114+00:00",38,{"name":50,"avatar":9},{"slug":13,"name":14,"color":15},[1112,1113],{"slug":54,"name":55},{"slug":1098,"name":1099},{"id":1115,"slug":1116,"title":1117,"excerpt":1118,"image":1119,"featured":447,"groupId":1120,"publishedAt":1121,"readingTime":1122,"views":48,"author":1123,"category":1124,"tags":1125},"633b6488-2a90-4632-86a5-9cff7ed52f08","javascript-event-loop-the-heart-of-non-blocking-concurrency-revisited-in-2025","JavaScript Event Loop: The Heart of Non-Blocking Concurrency — Revisited in 2025","The Event Loop is not just a simple loop, but a sophisticated coordination mechanism between Call Stack, queues, and runtime. Essential for JS concurrency, it enables thousands of asynchronous operations without blocking the UI. This guide explores its structure, differences between Node.js and browsers, common bugs, advanced techniques, and 2025 trends like Structured Concurrency and scheduler.yield().","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1772847201637-featured-oreiro.jpeg","df6ca967-8130-4b2d-bcac-3532a150131e","2026-07-26T18:54:25.359533+00:00",6,{"name":50,"avatar":9},{"slug":13,"name":14,"color":15},[1126,1127],{"slug":54,"name":55},{"slug":1128,"name":1129},"nodejs","Node.js",{"id":1131,"slug":1132,"title":1133,"excerpt":1134,"image":1135,"featured":447,"groupId":1136,"publishedAt":1137,"readingTime":23,"views":576,"author":1138,"category":1139,"tags":1140},"e63ce578-4726-46d2-8045-df6e4243657a","nextjs-16-ppr-eliminate-the-static-vs-dynamic-tradeoff-and-achieve-edge-ttfb-with-fresh-data","Next.js 16 PPR: Eliminate the static vs. dynamic tradeoff and achieve Edge TTFB with fresh data","Partial Prerendering in Next.js 16 resolves the classic rendering tradeoff, delivering static speed with dynamic data in one seamless response.","https:\u002F\u002Fmfgiomkkbihnlpfdxwrt.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fblog-assets\u002Fmedia\u002Ffeatured\u002F1783970715281-featured-ikveub.webp","4982f454-7d33-4921-a2b5-c1c663505594","2026-07-13T19:26:00.750741+00:00",{"name":50,"avatar":9},{"slug":13,"name":14,"color":15},[1141,1144,1147],{"slug":1142,"name":1143},"nextjs","Next.js",{"slug":1145,"name":1146},"react","React",{"slug":1098,"name":1099},{"en":40}]