1_N_E=(window.webpackJsonp_N_E=window.webpackJsonp_N_E||[]).push([[95],{AWTn:function(e,n,t){"use strict";t.d(n,"a",(function(){return o}));var a=t("nKUr");function o(){return Object(a.jsx)("style",{children:'\n .generated-blog-page {\n min-height: 100vh;\n padding-bottom: 80px;\n background: #f8fafc;\n color: #172033;\n font-family: Georgia, "Times New Roman", serif;\n }\n\n .generated-blog-page .hero,\n .generated-blog-page .tech-hero,\n .generated-blog-page .node-hero,\n .generated-blog-page > header {\n background-color: #102a43;\n background-position: center;\n background-size: cover;\n color: #ffffff;\n padding: 76px 0 64px;\n }\n\n .generated-blog-page .container,\n .generated-blog-page .tech-hero > div,\n .generated-blog-page .node-container,\n .generated-blog-page > header > div,\n .generated-blog-page > header:not(.hero) {\n width: min(1140px, calc(100% - 40px));\n margin: 0 auto;\n }\n\n .generated-blog-page .hero-grid {\n align-items: center;\n gap: 48px;\n }\n\n .generated-blog-page .hero h1,\n .generated-blog-page .tech-hero h1,\n .generated-blog-page .node-hero h1,\n .generated-blog-page > header h1 {\n max-width: 760px;\n margin: 14px 0 18px;\n color: #ffffff;\n font-size: clamp(2.5rem, 5vw, 4.5rem);\n line-height: 1.04;\n letter-spacing: 0;\n }\n\n .generated-blog-page .eyebrow,\n .generated-blog-page .tech-hero span,\n .generated-blog-page > header span {\n color: #7dd3fc;\n font-size: 0.78rem;\n font-weight: 700;\n letter-spacing: 0.12em;\n text-transform: uppercase;\n }\n\n .generated-blog-page .hero p,\n .generated-blog-page .tech-hero p,\n .generated-blog-page .node-hero p,\n .generated-blog-page > header p {\n max-width: 760px;\n color: #dbeafe;\n font-size: 1.12rem;\n line-height: 1.75;\n }\n\n .generated-blog-page .cover-image {\n border-radius: 8px;\n box-shadow: 0 24px 50px rgba(2, 18, 36, 0.3);\n }\n\n .generated-blog-page .content-layout,\n .generated-blog-page > .container.layout,\n .generated-blog-page > .layout {\n display: grid;\n grid-template-columns: 230px minmax(0, 1fr);\n gap: 42px;\n width: min(1140px, calc(100% - 40px));\n margin: 0 auto;\n padding: 54px 0 0;\n }\n\n .generated-blog-page .toc {\n position: sticky;\n top: 24px;\n align-self: start;\n padding: 18px;\n border: 1px solid #dbe4ee;\n border-radius: 8px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(15, 23, 42, 0.05);\n }\n\n .generated-blog-page .toc strong,\n .generated-blog-page .toc h3 {\n display: block;\n margin: 0 0 10px;\n color: #172033;\n font-size: 0.9rem;\n }\n\n .generated-blog-page .toc a {\n display: block;\n padding: 8px 0;\n border-bottom: 1px solid #edf2f7;\n color: #486581;\n font-size: 0.84rem;\n font-weight: 700;\n text-decoration: none;\n }\n\n .generated-blog-page .toc a:hover {\n color: #0e7490;\n }\n\n .generated-blog-page article,\n .generated-blog-page .node-article,\n .generated-blog-page > article {\n min-width: 0;\n padding: 40px 44px;\n border: 1px solid #dbe4ee;\n border-radius: 8px;\n background: #ffffff;\n box-shadow: 0 16px 40px rgba(15, 23, 42, 0.06);\n }\n\n .generated-blog-page article h2 {\n margin: 30px 0 12px;\n color: #172033;\n font-size: 2rem;\n line-height: 1.2;\n }\n\n .generated-blog-page article h2:first-child,\n .generated-blog-page article section:first-child h2 {\n margin-top: 0;\n }\n\n .generated-blog-page article h3 {\n color: #243b53;\n }\n\n .generated-blog-page article p,\n .generated-blog-page article li {\n color: #486581;\n font-size: 1.06rem;\n line-height: 1.8;\n }\n\n .generated-blog-page article a {\n color: #0e7490;\n font-weight: 700;\n }\n\n .generated-blog-page .callout,\n .generated-blog-page .tech-callout,\n .generated-blog-page .compare-callout,\n .generated-blog-page .highlight-box,\n .generated-blog-page .note {\n border-left: 4px solid #0e7490;\n border-radius: 4px;\n background: #ecfeff;\n color: #164e63;\n }\n\n .generated-blog-page pre {\n overflow-x: auto;\n border-radius: 6px;\n background: #102a43;
1\n color: #e0f2fe;\n }\n\n @media (max-width: 900px) {\n .generated-blog-page .content-layout,\n .generated-blog-page > .container.layout,\n .generated-blog-page > .layout {\n grid-template-columns: 1fr;\n }\n\n .generated-blog-page .toc {\n position: static;\n }\n }\n\n @media (max-width: 620px) {\n .generated-blog-page .hero,\n .generated-blog-page .tech-hero,\n .generated-blog-page .node-hero,\n .generated-blog-page > header {\n padding: 58px 0 46px;\n }\n\n .generated-blog-page .container,\n .generated-blog-page .tech-hero > div,\n .generated-blog-page .node-container,\n .generated-blog-page > header > div,\n .generated-blog-page > header:not(.hero),\n .generated-blog-page .content-layout,\n .generated-blog-page > .container.layout,\n .generated-blog-page > .layout {\n width: min(100% - 28px, 680px);\n }\n\n .generated-blog-page article,\n .generated-blog-page > article {\n padding: 28px 22px;\n }\n\n .generated-blog-page article h2 {\n font-size: 1.65rem;\n }\n }\n '})}},OmWg:function(e,n,t){"use strict";t.r(n),t.d(n,"default",(function(){return p}));var a=t("nKUr"),o=t("g4pe"),r=t.n(o),i=t("ZfMW"),d=t("AWTn"),g="Building Scalable Node.js APIs: Architecture Decisions That Matter",l="Learn how to design scalable Node.js APIs with clear boundaries, validation, observability, caching, rate limits, and dependable error handling.",c="/img/blog-covers/building-scalable-nodejs-apis.svg",s="https://www.endurancesoftwares.com/blog/building-scalable-nodejs-apis";function p(){return Object(a.jsxs)(i.a,{children:[Object(a.jsxs)(r.a,{children:[Object(a.jsxs)("title",{children:[g," | Endurance Softwares"]}),Object(a.jsx)("meta",{name:"description",content:l}),Object(a.jsx)("meta",{name:"keywords",content:"Node.js API development, scalable Node.js APIs, Node.js architecture, REST API development, backend architecture"}),Object(a.jsx)("link",{rel:"canonical",href:s}),Object(a.jsx)("meta",{property:"og:type",content:"article"}),Object(a.jsx)("meta",{property:"og:title",content:g}),Object(a.jsx)("meta",{property:"og:description",content:l}),Object(a.jsx)("meta",{property:"og:url",content:s}),Object(a.jsx)("meta",{property:"og:image",content:"https://www.endurancesoftwares.com".concat(c)}),Object(a.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),Object(a.jsx)("meta",{name:"twitter:title",content:g}),Object(a.jsx)("meta",{name:"twitter:description",content:l}),Object(a.jsx)("meta",{name:"twitter:image",content:"https://www.endurancesoftwares.com".concat(c)})]}),Object(a.jsxs)("main",{className:"node-blog generated-blog-page",children:[Object(a.jsx)("header",{className:"node-hero",style:{backgroundImage:'\n linear-gradient(\n 90deg,\n rgba(217, 107, 66, 0.96),\n rgba(217, 107, 66, 0.64)\n ),\n url("'.concat(c,'")\n ')},children:Object(a.jsxs)("div",{className:"node-container",children:[Object(a.jsx)("span",{className:"node-category",children:"Node.js Development"}),Object(a.jsx)("h1",{children:g}),Object(a.jsx)("p",{children:"Scalability begins with boundaries that remain understandable as traffic, teams, and business rules grow."})]})}),Object(a.jsxs)("article",{className:"node-article",children:[Object(a.jsx)("h2",{children:"Start with a clear request lifecycle"}),Object(a.jsx)("p",{children:"Keep routing, validation, business logic, persistence, and response formatting separate. This makes responsibilities easier to test and prevents controllers from becoming a second application hidden inside the HTTP layer."}),Object(a.jsx)("h2",{children:"Validate at the edge"}),Object(a.jsx)("p",{children:"Reject malformed input before it reaches domain logic. Use consistent schemas for body, query, and path parameters, and return errors that tell clients which field needs attention without exposing internal details."}),Object(a.jsx)("h2",{children:"Design for retries and duplicates"}),Object(a.jsx)("p",{children:"Networks fail and clients retry. For payments, orders, webhooks, and other state-changing operations, use idempotency keys or unique constraints so a repeated request cannot create repeated business effects."}),Object(a.jsx)("h2",{children:"Make dependency failures explicit"}),Object(a.jsx)("p",{children:"Databases, queues, and third-party services will occasionally be slow or unavailable. Add timeouts, bounded retries, circuit breakers where appropriate, and fallback behaviour that matches the business risk."}),Object(a.jsx)("h2",{children:"Build observability into the API"}),Object(a.jsxs)("ul",{children:[Object(a.jsx)("li",{children:"Attach a request ID to logs and responses."}),Object(a.jsx)("li",{children:"Record latency by route and status code."}),Object(a.jsx)("li",{children:"Track dependency timing separately from total request time."}),Object(a.jsx)("li",{children:"Alert on error rates and saturation, not only server crashes."})]}),Object(a.jsx)("h2",{children:"Scale the simple things first"}
1),Object(a.jsx)("p",{children:"Before adding complex infrastructure, remove avoidable work from the request path, add database indexes, paginate large responses, cache stable reads, and move slow jobs to a queue. A measured bottleneck should drive the next architectural change."}),Object(a.jsxs)("div",{className:"node-callout",children:[Object(a.jsx)("strong",{children:"Good API architecture:"})," A new engineer can trace one request from route to response without needing a map of hidden side effects."]})]}),Object(a.jsx)(d.a,{})]}),Object(a.jsx)("style",{children:"\n .node-blog {\n min-height: 100vh;\n padding-bottom: 80px;\n background: #fffaf0;\n color: #193630;\n }\n\n .node-hero {\n padding: 90px 24px;\n background-color: #d96b42;\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n color: #fffaf0;\n }\n\n .node-container {\n width: 100%;\n max-width: 850px;\n margin: 0 auto;\n }\n\n .node-category {\n display: inline-block;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 1.5px;\n text-transform: uppercase;\n }\n\n .node-blog h1 {\n max-width: 850px;\n margin: 18px 0 20px;\n font-size: clamp(42px, 6vw, 70px);\n line-height: 1.05;\n letter-spacing: -0.03em;\n }\n\n .node-hero p {\n max-width: 700px;\n margin: 0;\n color: #fffaf0;\n font-size: 19px;\n line-height: 1.7;\n }\n\n .node-article {\n width: 100%;\n max-width: 850px;\n margin: 0 auto;\n padding: 65px 24px 0;\n box-sizing: border-box;\n }\n\n .node-blog h2 {\n margin: 40px 0 12px;\n color: #193630;\n font-size: 32px;\n line-height: 1.25;\n }\n\n .node-blog h2:first-child {\n margin-top: 0;\n }\n\n .node-blog p,\n .node-blog li {\n color: #536d67;\n font-size: 17px;\n line-height: 1.8;\n }\n\n .node-article p {\n margin: 0;\n }\n\n .node-blog ul {\n margin: 15px 0 0;\n padding-left: 24px;\n }\n\n .node-blog li {\n margin-bottom: 7px;\n }\n\n .node-callout {\n margin-top: 40px;\n padding: 22px;\n border-left: 5px solid #193630;\n background: #e7d6b8;\n color: #193630;\n font-size: 17px;\n line-height: 1.7;\n }\n\n @media (max-width: 600px) {\n .node-blog {\n padding-bottom: 50px;\n }\n\n .node-hero {\n padding: 60px 18px;\n }\n\n .node-blog h1 {\n font-size: 40px;\n }\n\n .node-hero p {\n font-size: 17px;\n }\n\n .node-article {\n padding: 45px 18px 0;\n }\n\n .node-blog h2 {\n margin-top: 34px;\n font-size: 27px;\n }\n\n .node-blog p,\n .node-blog li {\n font-size: 16px;\n }\n }\n "})]})}},m9Pz:function(e,n,t){(window.__NEXT_P=window.__NEXT_P||[]).push(["/blog/building-scalable-nodejs-apis",function(){return t("OmWg")}])}},[["m9Pz",0,2,1,3,4,5,6,7,8]]]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.