[{"data":1,"prerenderedAt":9074},["ShallowReactive",2],{"footer-blog-posts":3,"blog-/blog/signs-outgrown-infrastructure":3626,"blog-related-/blog/signs-outgrown-infrastructure":5182},[4,2422],{"id":5,"title":6,"author":7,"body":10,"category":2406,"coverImage":2407,"date":2408,"description":2409,"extension":2410,"featured":2411,"meta":2412,"navigation":365,"path":2413,"readingTime":2414,"seo":2415,"stem":2416,"tags":2417,"__hash__":2421},"blog/blog/api-first-approach-guide.md","The API-First Approach: Why Leading Companies Build APIs Before Interfaces",{"name":8,"role":9},"Sahan De Silva","Lead Cloud Architect",{"type":11,"value":12,"toc":2373},"minimark",[13,18,27,30,36,40,43,46,68,71,75,78,83,89,95,99,104,109,113,118,123,212,216,219,223,226,235,239,242,246,254,262,266,269,273,276,280,283,1086,1089,1093,1096,1158,1161,1172,1176,1179,1667,1670,1674,1677,1689,1698,1707,1710,1725,1729,1732,1927,1930,1950,1955,1959,1962,1966,2010,2018,2022,2025,2029,2032,2036,2051,2055,2058,2169,2172,2176,2184,2188,2195,2303,2306,2310,2313,2345,2348,2356,2359,2369],[14,15,17],"h2",{"id":16},"apis-are-products-not-plumbing","APIs Are Products, Not Plumbing",[19,20,21,22,26],"p",{},"The most successful software companies in the world — Stripe, Twilio, Shopify — share a common trait: they treat their APIs as first-class products. The ",[23,24,25],"strong",{},"API-first approach"," means designing the API contract before writing any implementation code, ensuring that every system, team, and future integration builds on a stable, well-documented foundation. This methodology is no longer a luxury for platform companies. It is essential for any business building interconnected digital systems that need to scale.",[19,28,29],{},"If you have ever struggled with a mobile app that does not match the web experience, a third-party integration that breaks after every release, or frontend and backend teams blocking each other's progress, API-first development solves these problems by design.",[31,32,33],"blockquote",{},[19,34,35],{},"The best time to adopt API-first was at the start of your project. The second-best time is now, before your next breaking change costs you a customer.",[14,37,39],{"id":38},"what-is-api-first-development","What Is API-First Development?",[19,41,42],{},"API-first development is a methodology where the API specification is designed, reviewed, and agreed upon before any implementation work begins. The API contract becomes the single source of truth that all teams — frontend, backend, mobile, QA, and external partners — build against.",[19,44,45],{},"This inverts the traditional approach where APIs are an afterthought, bolted onto existing backend code and shaped by database schemas rather than consumer needs. In an API-first workflow:",[47,48,49,53,56,59,62,65],"ol",{},[50,51,52],"li",{},"Stakeholders agree on the API contract (what data goes in, what comes out, what errors are possible)",[50,54,55],{},"The contract is documented in a machine-readable specification (OpenAPI, GraphQL SDL)",[50,57,58],{},"Mock servers are generated from the specification, enabling parallel development",[50,60,61],{},"Frontend, mobile, and backend teams build simultaneously against the contract",[50,63,64],{},"Contract tests verify that implementations match the specification",[50,66,67],{},"The API is versioned and maintained as a product, with its own lifecycle",[19,69,70],{},"This approach fundamentally changes how teams collaborate, how quickly features ship, and how reliably systems integrate.",[14,72,74],{"id":73},"api-first-vs-code-first-what-changes","API-First vs Code-First: What Changes",[19,76,77],{},"The differences between API-first and code-first development are practical, not just philosophical. Here is how each phase of development changes.",[79,80,82],"h3",{"id":81},"design-phase","Design Phase",[19,84,85,88],{},[23,86,87],{},"Code-first",": A backend developer builds an endpoint, documents it in a wiki or Swagger annotation, and shares it with the frontend team. The frontend team discovers edge cases, requests changes, and both teams iterate — often through a slow cycle of PRs, Slack messages, and meetings.",[19,90,91,94],{},[23,92,93],{},"API-first",": Stakeholders (product, frontend, backend, mobile) review the API specification together before any code is written. Disagreements about data shapes, naming conventions, and error handling are resolved in a document, not in pull requests. Mock servers let everyone validate the design against real use cases.",[79,96,98],{"id":97},"development-phase","Development Phase",[19,100,101,103],{},[23,102,87],{},": Frontend teams wait for backend endpoints to be ready. This creates sequential dependencies and idle time. When the backend delivers an endpoint, its shape often does not match frontend expectations, triggering rework.",[19,105,106,108],{},[23,107,93],{},": Frontend and backend teams work in parallel from day one. The frontend builds against mock servers generated from the specification. The backend implements against the same specification. When both sides are done, integration is a formality because the contract was agreed upon upfront.",[79,110,112],{"id":111},"testing-phase","Testing Phase",[19,114,115,117],{},[23,116,87],{},": Integration tests are written after both sides are built, discovering contract mismatches late in the cycle.",[19,119,120,122],{},[23,121,93],{},": Contract tests run continuously, verifying that implementations conform to the specification. Consumer-driven contract testing ensures that API changes do not break existing consumers.",[124,125,126,142],"table",{},[127,128,129],"thead",{},[130,131,132,136,139],"tr",{},[133,134,135],"th",{},"Aspect",[133,137,138],{},"Code-First",[133,140,141],{},"API-First",[143,144,145,157,168,179,190,201],"tbody",{},[130,146,147,151,154],{},[148,149,150],"td",{},"Design input",[148,152,153],{},"Backend developer",[148,155,156],{},"Cross-functional stakeholders",[130,158,159,162,165],{},[148,160,161],{},"Specification",[148,163,164],{},"Generated from code (afterthought)",[148,166,167],{},"Written first (source of truth)",[130,169,170,173,176],{},[148,171,172],{},"Parallel development",[148,174,175],{},"Limited (sequential dependencies)",[148,177,178],{},"Full (mock servers from day one)",[130,180,181,184,187],{},[148,182,183],{},"Contract validation",[148,185,186],{},"Manual / late integration testing",[148,188,189],{},"Automated contract testing",[130,191,192,195,198],{},[148,193,194],{},"Documentation",[148,196,197],{},"Often stale",[148,199,200],{},"Always current (generated from spec)",[130,202,203,206,209],{},[148,204,205],{},"Breaking change risk",[148,207,208],{},"High (discovered in production)",[148,210,211],{},"Low (caught in CI)",[14,213,215],{"id":214},"the-business-case-for-api-first","The Business Case for API-First",[19,217,218],{},"API-first development is not just an engineering preference. It delivers measurable business value across multiple dimensions.",[79,220,222],{"id":221},"faster-parallel-development","Faster Parallel Development",[19,224,225],{},"When frontend and backend teams can work simultaneously, feature delivery accelerates by 30-50%. There is no \"waiting for the API\" phase. Mobile developers are not blocked by web developers. External partners can start integration work before your internal implementation is complete.",[19,227,228,229,234],{},"For businesses working with an ",[230,231,233],"a",{"href":232},"/solutions/api-integrations","integration engineering partner",", this parallel development capability is transformative. It compresses timelines and reduces the coordination overhead that slows most projects.",[79,236,238],{"id":237},"better-partner-and-third-party-integrations","Better Partner and Third-Party Integrations",[19,240,241],{},"If your business relies on third-party integrations — payment processors, shipping providers, CRM systems, marketing platforms — a well-designed API layer makes these integrations predictable and maintainable. Partners build against your documented API, not against the quirks of your internal implementation.",[79,243,245],{"id":244},"future-proofing-your-technology-stack","Future-Proofing Your Technology Stack",[19,247,248,249,253],{},"A well-designed API layer decouples your business logic from any specific frontend or consumer. Today, your API serves a web application. Tomorrow, it serves a mobile app, an AI agent like ",[230,250,252],{"href":251},"/solutions/connekz-integration","Connekz",", an IoT device, or a partner's platform — all without changing the backend.",[19,255,256,257,261],{},"This flexibility is particularly valuable for businesses planning ",[230,258,260],{"href":259},"/solutions/mobile-apps","mobile application development",". When the API is designed independently of the web frontend, the mobile app gets the same first-class data access without workarounds or BFF (Backend for Frontend) layers.",[79,263,265],{"id":264},"reduced-rework-and-miscommunication","Reduced Rework and Miscommunication",[19,267,268],{},"The most expensive bugs are specification bugs — building the wrong thing. API-first development forces specification alignment before code is written. The cost of changing a YAML file is trivially small compared to refactoring implemented code across multiple teams and codebases.",[14,270,272],{"id":271},"implementation-patterns","Implementation Patterns",[19,274,275],{},"Moving from theory to practice requires specific tools, patterns, and workflows. Here is how to implement API-first development in your organisation.",[79,277,279],{"id":278},"openapi-specification-design","OpenAPI Specification Design",[19,281,282],{},"The OpenAPI Specification (formerly Swagger) is the industry standard for describing REST APIs. Your API specification should be the first artifact created for any new feature or service.",[284,285,290],"pre",{"className":286,"code":287,"language":288,"meta":289,"style":289},"language-yaml shiki shiki-themes github-light github-dark","# openapi.yaml — Example specification for a booking API\nopenapi: 3.1.0\ninfo:\n  title: Booking API\n  version: 2.0.0\n  description: API for managing customer bookings and appointments\n\npaths:\n  /bookings:\n    post:\n      operationId: createBooking\n      summary: Create a new booking\n      tags:\n        - Bookings\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              $ref: '#/components/schemas/CreateBookingRequest'\n      responses:\n        '201':\n          description: Booking created successfully\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/BookingResponse'\n        '409':\n          description: Time slot no longer available\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ErrorResponse'\n        '422':\n          description: Validation error\n          content:\n            application/json:\n              schema:\n                $ref: '#/components/schemas/ValidationErrorResponse'\n\ncomponents:\n  schemas:\n    CreateBookingRequest:\n      type: object\n      required:\n        - serviceType\n        - dateTime\n        - customerName\n        - customerEmail\n      properties:\n        serviceType:\n          type: string\n          enum:\n            - consultation\n            - follow-up\n            - treatment\n        dateTime:\n          type: string\n          format: date-time\n          description: ISO 8601 date-time for the appointment\n        customerName:\n          type: string\n          minLength: 2\n          maxLength: 100\n        customerEmail:\n          type: string\n          format: email\n        notes:\n          type: string\n          maxLength: 500\n\n    BookingResponse:\n      type: object\n      properties:\n        id:\n          type: string\n          format: uuid\n        status:\n          type: string\n          enum:\n            - confirmed\n            - pending\n            - cancelled\n        serviceType:\n          type: string\n        dateTime:\n          type: string\n          format: date-time\n        createdAt:\n          type: string\n          format: date-time\n","yaml","",[291,292,293,302,317,326,338,349,360,367,375,383,391,402,413,421,430,438,449,457,465,473,484,492,500,511,519,527,535,546,554,564,571,578,585,595,603,613,620,627,634,644,649,657,665,673,684,692,700,708,716,724,732,740,751,759,768,776,784,792,801,812,822,830,839,850,861,869,878,888,896,905,915,920,928,937,944,952,961,971,979,988,995,1003,1011,1019,1026,1035,1042,1051,1060,1068,1077],"code",{"__ignoreMap":289},[294,295,298],"span",{"class":296,"line":297},"line",1,[294,299,301],{"class":300},"sJ8bj","# openapi.yaml — Example specification for a booking API\n",[294,303,305,309,313],{"class":296,"line":304},2,[294,306,308],{"class":307},"s9eBZ","openapi",[294,310,312],{"class":311},"sVt8B",": ",[294,314,316],{"class":315},"sj4cs","3.1.0\n",[294,318,320,323],{"class":296,"line":319},3,[294,321,322],{"class":307},"info",[294,324,325],{"class":311},":\n",[294,327,329,332,334],{"class":296,"line":328},4,[294,330,331],{"class":307},"  title",[294,333,312],{"class":311},[294,335,337],{"class":336},"sZZnC","Booking API\n",[294,339,341,344,346],{"class":296,"line":340},5,[294,342,343],{"class":307},"  version",[294,345,312],{"class":311},[294,347,348],{"class":315},"2.0.0\n",[294,350,352,355,357],{"class":296,"line":351},6,[294,353,354],{"class":307},"  description",[294,356,312],{"class":311},[294,358,359],{"class":336},"API for managing customer bookings and appointments\n",[294,361,363],{"class":296,"line":362},7,[294,364,366],{"emptyLinePlaceholder":365},true,"\n",[294,368,370,373],{"class":296,"line":369},8,[294,371,372],{"class":307},"paths",[294,374,325],{"class":311},[294,376,378,381],{"class":296,"line":377},9,[294,379,380],{"class":307},"  /bookings",[294,382,325],{"class":311},[294,384,386,389],{"class":296,"line":385},10,[294,387,388],{"class":307},"    post",[294,390,325],{"class":311},[294,392,394,397,399],{"class":296,"line":393},11,[294,395,396],{"class":307},"      operationId",[294,398,312],{"class":311},[294,400,401],{"class":336},"createBooking\n",[294,403,405,408,410],{"class":296,"line":404},12,[294,406,407],{"class":307},"      summary",[294,409,312],{"class":311},[294,411,412],{"class":336},"Create a new booking\n",[294,414,416,419],{"class":296,"line":415},13,[294,417,418],{"class":307},"      tags",[294,420,325],{"class":311},[294,422,424,427],{"class":296,"line":423},14,[294,425,426],{"class":311},"        - ",[294,428,429],{"class":336},"Bookings\n",[294,431,433,436],{"class":296,"line":432},15,[294,434,435],{"class":307},"      requestBody",[294,437,325],{"class":311},[294,439,441,444,446],{"class":296,"line":440},16,[294,442,443],{"class":307},"        required",[294,445,312],{"class":311},[294,447,448],{"class":315},"true\n",[294,450,452,455],{"class":296,"line":451},17,[294,453,454],{"class":307},"        content",[294,456,325],{"class":311},[294,458,460,463],{"class":296,"line":459},18,[294,461,462],{"class":307},"          application/json",[294,464,325],{"class":311},[294,466,468,471],{"class":296,"line":467},19,[294,469,470],{"class":307},"            schema",[294,472,325],{"class":311},[294,474,476,479,481],{"class":296,"line":475},20,[294,477,478],{"class":307},"              $ref",[294,480,312],{"class":311},[294,482,483],{"class":336},"'#/components/schemas/CreateBookingRequest'\n",[294,485,487,490],{"class":296,"line":486},21,[294,488,489],{"class":307},"      responses",[294,491,325],{"class":311},[294,493,495,498],{"class":296,"line":494},22,[294,496,497],{"class":336},"        '201'",[294,499,325],{"class":311},[294,501,503,506,508],{"class":296,"line":502},23,[294,504,505],{"class":307},"          description",[294,507,312],{"class":311},[294,509,510],{"class":336},"Booking created successfully\n",[294,512,514,517],{"class":296,"line":513},24,[294,515,516],{"class":307},"          content",[294,518,325],{"class":311},[294,520,522,525],{"class":296,"line":521},25,[294,523,524],{"class":307},"            application/json",[294,526,325],{"class":311},[294,528,530,533],{"class":296,"line":529},26,[294,531,532],{"class":307},"              schema",[294,534,325],{"class":311},[294,536,538,541,543],{"class":296,"line":537},27,[294,539,540],{"class":307},"                $ref",[294,542,312],{"class":311},[294,544,545],{"class":336},"'#/components/schemas/BookingResponse'\n",[294,547,549,552],{"class":296,"line":548},28,[294,550,551],{"class":336},"        '409'",[294,553,325],{"class":311},[294,555,557,559,561],{"class":296,"line":556},29,[294,558,505],{"class":307},[294,560,312],{"class":311},[294,562,563],{"class":336},"Time slot no longer available\n",[294,565,567,569],{"class":296,"line":566},30,[294,568,516],{"class":307},[294,570,325],{"class":311},[294,572,574,576],{"class":296,"line":573},31,[294,575,524],{"class":307},[294,577,325],{"class":311},[294,579,581,583],{"class":296,"line":580},32,[294,582,532],{"class":307},[294,584,325],{"class":311},[294,586,588,590,592],{"class":296,"line":587},33,[294,589,540],{"class":307},[294,591,312],{"class":311},[294,593,594],{"class":336},"'#/components/schemas/ErrorResponse'\n",[294,596,598,601],{"class":296,"line":597},34,[294,599,600],{"class":336},"        '422'",[294,602,325],{"class":311},[294,604,606,608,610],{"class":296,"line":605},35,[294,607,505],{"class":307},[294,609,312],{"class":311},[294,611,612],{"class":336},"Validation error\n",[294,614,616,618],{"class":296,"line":615},36,[294,617,516],{"class":307},[294,619,325],{"class":311},[294,621,623,625],{"class":296,"line":622},37,[294,624,524],{"class":307},[294,626,325],{"class":311},[294,628,630,632],{"class":296,"line":629},38,[294,631,532],{"class":307},[294,633,325],{"class":311},[294,635,637,639,641],{"class":296,"line":636},39,[294,638,540],{"class":307},[294,640,312],{"class":311},[294,642,643],{"class":336},"'#/components/schemas/ValidationErrorResponse'\n",[294,645,647],{"class":296,"line":646},40,[294,648,366],{"emptyLinePlaceholder":365},[294,650,652,655],{"class":296,"line":651},41,[294,653,654],{"class":307},"components",[294,656,325],{"class":311},[294,658,660,663],{"class":296,"line":659},42,[294,661,662],{"class":307},"  schemas",[294,664,325],{"class":311},[294,666,668,671],{"class":296,"line":667},43,[294,669,670],{"class":307},"    CreateBookingRequest",[294,672,325],{"class":311},[294,674,676,679,681],{"class":296,"line":675},44,[294,677,678],{"class":307},"      type",[294,680,312],{"class":311},[294,682,683],{"class":336},"object\n",[294,685,687,690],{"class":296,"line":686},45,[294,688,689],{"class":307},"      required",[294,691,325],{"class":311},[294,693,695,697],{"class":296,"line":694},46,[294,696,426],{"class":311},[294,698,699],{"class":336},"serviceType\n",[294,701,703,705],{"class":296,"line":702},47,[294,704,426],{"class":311},[294,706,707],{"class":336},"dateTime\n",[294,709,711,713],{"class":296,"line":710},48,[294,712,426],{"class":311},[294,714,715],{"class":336},"customerName\n",[294,717,719,721],{"class":296,"line":718},49,[294,720,426],{"class":311},[294,722,723],{"class":336},"customerEmail\n",[294,725,727,730],{"class":296,"line":726},50,[294,728,729],{"class":307},"      properties",[294,731,325],{"class":311},[294,733,735,738],{"class":296,"line":734},51,[294,736,737],{"class":307},"        serviceType",[294,739,325],{"class":311},[294,741,743,746,748],{"class":296,"line":742},52,[294,744,745],{"class":307},"          type",[294,747,312],{"class":311},[294,749,750],{"class":336},"string\n",[294,752,754,757],{"class":296,"line":753},53,[294,755,756],{"class":307},"          enum",[294,758,325],{"class":311},[294,760,762,765],{"class":296,"line":761},54,[294,763,764],{"class":311},"            - ",[294,766,767],{"class":336},"consultation\n",[294,769,771,773],{"class":296,"line":770},55,[294,772,764],{"class":311},[294,774,775],{"class":336},"follow-up\n",[294,777,779,781],{"class":296,"line":778},56,[294,780,764],{"class":311},[294,782,783],{"class":336},"treatment\n",[294,785,787,790],{"class":296,"line":786},57,[294,788,789],{"class":307},"        dateTime",[294,791,325],{"class":311},[294,793,795,797,799],{"class":296,"line":794},58,[294,796,745],{"class":307},[294,798,312],{"class":311},[294,800,750],{"class":336},[294,802,804,807,809],{"class":296,"line":803},59,[294,805,806],{"class":307},"          format",[294,808,312],{"class":311},[294,810,811],{"class":336},"date-time\n",[294,813,815,817,819],{"class":296,"line":814},60,[294,816,505],{"class":307},[294,818,312],{"class":311},[294,820,821],{"class":336},"ISO 8601 date-time for the appointment\n",[294,823,825,828],{"class":296,"line":824},61,[294,826,827],{"class":307},"        customerName",[294,829,325],{"class":311},[294,831,833,835,837],{"class":296,"line":832},62,[294,834,745],{"class":307},[294,836,312],{"class":311},[294,838,750],{"class":336},[294,840,842,845,847],{"class":296,"line":841},63,[294,843,844],{"class":307},"          minLength",[294,846,312],{"class":311},[294,848,849],{"class":315},"2\n",[294,851,853,856,858],{"class":296,"line":852},64,[294,854,855],{"class":307},"          maxLength",[294,857,312],{"class":311},[294,859,860],{"class":315},"100\n",[294,862,864,867],{"class":296,"line":863},65,[294,865,866],{"class":307},"        customerEmail",[294,868,325],{"class":311},[294,870,872,874,876],{"class":296,"line":871},66,[294,873,745],{"class":307},[294,875,312],{"class":311},[294,877,750],{"class":336},[294,879,881,883,885],{"class":296,"line":880},67,[294,882,806],{"class":307},[294,884,312],{"class":311},[294,886,887],{"class":336},"email\n",[294,889,891,894],{"class":296,"line":890},68,[294,892,893],{"class":307},"        notes",[294,895,325],{"class":311},[294,897,899,901,903],{"class":296,"line":898},69,[294,900,745],{"class":307},[294,902,312],{"class":311},[294,904,750],{"class":336},[294,906,908,910,912],{"class":296,"line":907},70,[294,909,855],{"class":307},[294,911,312],{"class":311},[294,913,914],{"class":315},"500\n",[294,916,918],{"class":296,"line":917},71,[294,919,366],{"emptyLinePlaceholder":365},[294,921,923,926],{"class":296,"line":922},72,[294,924,925],{"class":307},"    BookingResponse",[294,927,325],{"class":311},[294,929,931,933,935],{"class":296,"line":930},73,[294,932,678],{"class":307},[294,934,312],{"class":311},[294,936,683],{"class":336},[294,938,940,942],{"class":296,"line":939},74,[294,941,729],{"class":307},[294,943,325],{"class":311},[294,945,947,950],{"class":296,"line":946},75,[294,948,949],{"class":307},"        id",[294,951,325],{"class":311},[294,953,955,957,959],{"class":296,"line":954},76,[294,956,745],{"class":307},[294,958,312],{"class":311},[294,960,750],{"class":336},[294,962,964,966,968],{"class":296,"line":963},77,[294,965,806],{"class":307},[294,967,312],{"class":311},[294,969,970],{"class":336},"uuid\n",[294,972,974,977],{"class":296,"line":973},78,[294,975,976],{"class":307},"        status",[294,978,325],{"class":311},[294,980,982,984,986],{"class":296,"line":981},79,[294,983,745],{"class":307},[294,985,312],{"class":311},[294,987,750],{"class":336},[294,989,991,993],{"class":296,"line":990},80,[294,992,756],{"class":307},[294,994,325],{"class":311},[294,996,998,1000],{"class":296,"line":997},81,[294,999,764],{"class":311},[294,1001,1002],{"class":336},"confirmed\n",[294,1004,1006,1008],{"class":296,"line":1005},82,[294,1007,764],{"class":311},[294,1009,1010],{"class":336},"pending\n",[294,1012,1014,1016],{"class":296,"line":1013},83,[294,1015,764],{"class":311},[294,1017,1018],{"class":336},"cancelled\n",[294,1020,1022,1024],{"class":296,"line":1021},84,[294,1023,737],{"class":307},[294,1025,325],{"class":311},[294,1027,1029,1031,1033],{"class":296,"line":1028},85,[294,1030,745],{"class":307},[294,1032,312],{"class":311},[294,1034,750],{"class":336},[294,1036,1038,1040],{"class":296,"line":1037},86,[294,1039,789],{"class":307},[294,1041,325],{"class":311},[294,1043,1045,1047,1049],{"class":296,"line":1044},87,[294,1046,745],{"class":307},[294,1048,312],{"class":311},[294,1050,750],{"class":336},[294,1052,1054,1056,1058],{"class":296,"line":1053},88,[294,1055,806],{"class":307},[294,1057,312],{"class":311},[294,1059,811],{"class":336},[294,1061,1063,1066],{"class":296,"line":1062},89,[294,1064,1065],{"class":307},"        createdAt",[294,1067,325],{"class":311},[294,1069,1071,1073,1075],{"class":296,"line":1070},90,[294,1072,745],{"class":307},[294,1074,312],{"class":311},[294,1076,750],{"class":336},[294,1078,1080,1082,1084],{"class":296,"line":1079},91,[294,1081,806],{"class":307},[294,1083,312],{"class":311},[294,1085,811],{"class":336},[19,1087,1088],{},"This specification is machine-readable. From it, you can generate mock servers, client SDKs, validation middleware, and interactive documentation — all automatically.",[79,1090,1092],{"id":1091},"mock-first-development","Mock-First Development",[19,1094,1095],{},"Once the specification is written, generate mock servers so that consumer teams can start building immediately.",[284,1097,1101],{"className":1098,"code":1099,"language":1100,"meta":289,"style":289},"language-bash shiki shiki-themes github-light github-dark","# Generate a mock server from your OpenAPI spec using Prism\nnpx @stoplight/prism-cli mock openapi.yaml --port 4010\n\n# Or use MSW (Mock Service Worker) for frontend testing\n# msw generates handlers from OpenAPI specs\nnpx msw-auto-mock openapi.yaml --output ./src/mocks/handlers.ts\n","bash",[291,1102,1103,1108,1129,1133,1138,1143],{"__ignoreMap":289},[294,1104,1105],{"class":296,"line":297},[294,1106,1107],{"class":300},"# Generate a mock server from your OpenAPI spec using Prism\n",[294,1109,1110,1114,1117,1120,1123,1126],{"class":296,"line":304},[294,1111,1113],{"class":1112},"sScJk","npx",[294,1115,1116],{"class":336}," @stoplight/prism-cli",[294,1118,1119],{"class":336}," mock",[294,1121,1122],{"class":336}," openapi.yaml",[294,1124,1125],{"class":315}," --port",[294,1127,1128],{"class":315}," 4010\n",[294,1130,1131],{"class":296,"line":319},[294,1132,366],{"emptyLinePlaceholder":365},[294,1134,1135],{"class":296,"line":328},[294,1136,1137],{"class":300},"# Or use MSW (Mock Service Worker) for frontend testing\n",[294,1139,1140],{"class":296,"line":340},[294,1141,1142],{"class":300},"# msw generates handlers from OpenAPI specs\n",[294,1144,1145,1147,1150,1152,1155],{"class":296,"line":351},[294,1146,1113],{"class":1112},[294,1148,1149],{"class":336}," msw-auto-mock",[294,1151,1122],{"class":336},[294,1153,1154],{"class":315}," --output",[294,1156,1157],{"class":336}," ./src/mocks/handlers.ts\n",[19,1159,1160],{},"Mock servers return realistic responses based on the schemas in your specification. Frontend developers build against these mocks, confident that the real API will return data in the same shape.",[1162,1163,1165],"callout",{"type":1164},"tip",[19,1166,1167,1168,1171],{},"Invest time in adding ",[291,1169,1170],{},"example"," values to your OpenAPI schemas. Mocks generated from well-annotated specifications are realistic enough that frontend teams can complete full feature development without ever touching the real backend.",[79,1173,1175],{"id":1174},"contract-testing-with-pact","Contract Testing with Pact",[19,1177,1178],{},"Contract testing verifies that API producers and consumers agree on the interface. Pact is the most widely adopted tool for consumer-driven contract testing.",[284,1180,1184],{"className":1181,"code":1182,"language":1183,"meta":289,"style":289},"language-typescript shiki shiki-themes github-light github-dark","// Consumer-side contract test (frontend/mobile team writes this)\nimport { PactV4 } from '@pact-foundation/pact';\n\nconst provider = new PactV4({\n  consumer: 'BookingWebApp',\n  provider: 'BookingAPI',\n});\n\ndescribe('Booking API Contract', () => {\n  it('creates a booking successfully', async () => {\n    await provider\n      .addInteraction()\n      .given('available time slot exists')\n      .uponReceiving('a request to create a booking')\n      .withRequest('POST', '/bookings', (builder) => {\n        builder\n          .headers({ 'Content-Type': 'application/json' })\n          .jsonBody({\n            serviceType: 'consultation',\n            dateTime: '2026-02-17T14:30:00Z',\n            customerName: 'Sarah Chen',\n            customerEmail: 'sarah@example.com',\n          });\n      })\n      .willRespondWith(201, (builder) => {\n        builder.jsonBody({\n          id: provider.like('f47ac10b-58cc-4372-a567-0e02b2c3d479'),\n          status: 'confirmed',\n          serviceType: 'consultation',\n          dateTime: '2026-02-17T14:30:00Z',\n        });\n      })\n      .executeTest(async (mockServer) => {\n        const response = await createBooking(mockServer.url, {\n          serviceType: 'consultation',\n          dateTime: '2026-02-17T14:30:00Z',\n          customerName: 'Sarah Chen',\n          customerEmail: 'sarah@example.com',\n        });\n        expect(response.status).toBe('confirmed');\n      });\n  });\n});\n","typescript",[291,1185,1186,1191,1209,1213,1233,1244,1254,1259,1263,1283,1306,1314,1325,1340,1354,1385,1390,1412,1421,1431,1441,1451,1461,1466,1471,1493,1502,1518,1528,1537,1546,1551,1555,1578,1597,1605,1613,1622,1631,1635,1653,1658,1663],{"__ignoreMap":289},[294,1187,1188],{"class":296,"line":297},[294,1189,1190],{"class":300},"// Consumer-side contract test (frontend/mobile team writes this)\n",[294,1192,1193,1197,1200,1203,1206],{"class":296,"line":304},[294,1194,1196],{"class":1195},"szBVR","import",[294,1198,1199],{"class":311}," { PactV4 } ",[294,1201,1202],{"class":1195},"from",[294,1204,1205],{"class":336}," '@pact-foundation/pact'",[294,1207,1208],{"class":311},";\n",[294,1210,1211],{"class":296,"line":319},[294,1212,366],{"emptyLinePlaceholder":365},[294,1214,1215,1218,1221,1224,1227,1230],{"class":296,"line":328},[294,1216,1217],{"class":1195},"const",[294,1219,1220],{"class":315}," provider",[294,1222,1223],{"class":1195}," =",[294,1225,1226],{"class":1195}," new",[294,1228,1229],{"class":1112}," PactV4",[294,1231,1232],{"class":311},"({\n",[294,1234,1235,1238,1241],{"class":296,"line":340},[294,1236,1237],{"class":311},"  consumer: ",[294,1239,1240],{"class":336},"'BookingWebApp'",[294,1242,1243],{"class":311},",\n",[294,1245,1246,1249,1252],{"class":296,"line":351},[294,1247,1248],{"class":311},"  provider: ",[294,1250,1251],{"class":336},"'BookingAPI'",[294,1253,1243],{"class":311},[294,1255,1256],{"class":296,"line":362},[294,1257,1258],{"class":311},"});\n",[294,1260,1261],{"class":296,"line":369},[294,1262,366],{"emptyLinePlaceholder":365},[294,1264,1265,1268,1271,1274,1277,1280],{"class":296,"line":377},[294,1266,1267],{"class":1112},"describe",[294,1269,1270],{"class":311},"(",[294,1272,1273],{"class":336},"'Booking API Contract'",[294,1275,1276],{"class":311},", () ",[294,1278,1279],{"class":1195},"=>",[294,1281,1282],{"class":311}," {\n",[294,1284,1285,1288,1290,1293,1296,1299,1302,1304],{"class":296,"line":385},[294,1286,1287],{"class":1112},"  it",[294,1289,1270],{"class":311},[294,1291,1292],{"class":336},"'creates a booking successfully'",[294,1294,1295],{"class":311},", ",[294,1297,1298],{"class":1195},"async",[294,1300,1301],{"class":311}," () ",[294,1303,1279],{"class":1195},[294,1305,1282],{"class":311},[294,1307,1308,1311],{"class":296,"line":393},[294,1309,1310],{"class":1195},"    await",[294,1312,1313],{"class":311}," provider\n",[294,1315,1316,1319,1322],{"class":296,"line":404},[294,1317,1318],{"class":311},"      .",[294,1320,1321],{"class":1112},"addInteraction",[294,1323,1324],{"class":311},"()\n",[294,1326,1327,1329,1332,1334,1337],{"class":296,"line":415},[294,1328,1318],{"class":311},[294,1330,1331],{"class":1112},"given",[294,1333,1270],{"class":311},[294,1335,1336],{"class":336},"'available time slot exists'",[294,1338,1339],{"class":311},")\n",[294,1341,1342,1344,1347,1349,1352],{"class":296,"line":423},[294,1343,1318],{"class":311},[294,1345,1346],{"class":1112},"uponReceiving",[294,1348,1270],{"class":311},[294,1350,1351],{"class":336},"'a request to create a booking'",[294,1353,1339],{"class":311},[294,1355,1356,1358,1361,1363,1366,1368,1371,1374,1378,1381,1383],{"class":296,"line":432},[294,1357,1318],{"class":311},[294,1359,1360],{"class":1112},"withRequest",[294,1362,1270],{"class":311},[294,1364,1365],{"class":336},"'POST'",[294,1367,1295],{"class":311},[294,1369,1370],{"class":336},"'/bookings'",[294,1372,1373],{"class":311},", (",[294,1375,1377],{"class":1376},"s4XuR","builder",[294,1379,1380],{"class":311},") ",[294,1382,1279],{"class":1195},[294,1384,1282],{"class":311},[294,1386,1387],{"class":296,"line":440},[294,1388,1389],{"class":311},"        builder\n",[294,1391,1392,1395,1398,1401,1404,1406,1409],{"class":296,"line":451},[294,1393,1394],{"class":311},"          .",[294,1396,1397],{"class":1112},"headers",[294,1399,1400],{"class":311},"({ ",[294,1402,1403],{"class":336},"'Content-Type'",[294,1405,312],{"class":311},[294,1407,1408],{"class":336},"'application/json'",[294,1410,1411],{"class":311}," })\n",[294,1413,1414,1416,1419],{"class":296,"line":459},[294,1415,1394],{"class":311},[294,1417,1418],{"class":1112},"jsonBody",[294,1420,1232],{"class":311},[294,1422,1423,1426,1429],{"class":296,"line":467},[294,1424,1425],{"class":311},"            serviceType: ",[294,1427,1428],{"class":336},"'consultation'",[294,1430,1243],{"class":311},[294,1432,1433,1436,1439],{"class":296,"line":475},[294,1434,1435],{"class":311},"            dateTime: ",[294,1437,1438],{"class":336},"'2026-02-17T14:30:00Z'",[294,1440,1243],{"class":311},[294,1442,1443,1446,1449],{"class":296,"line":486},[294,1444,1445],{"class":311},"            customerName: ",[294,1447,1448],{"class":336},"'Sarah Chen'",[294,1450,1243],{"class":311},[294,1452,1453,1456,1459],{"class":296,"line":494},[294,1454,1455],{"class":311},"            customerEmail: ",[294,1457,1458],{"class":336},"'sarah@example.com'",[294,1460,1243],{"class":311},[294,1462,1463],{"class":296,"line":502},[294,1464,1465],{"class":311},"          });\n",[294,1467,1468],{"class":296,"line":513},[294,1469,1470],{"class":311},"      })\n",[294,1472,1473,1475,1478,1480,1483,1485,1487,1489,1491],{"class":296,"line":521},[294,1474,1318],{"class":311},[294,1476,1477],{"class":1112},"willRespondWith",[294,1479,1270],{"class":311},[294,1481,1482],{"class":315},"201",[294,1484,1373],{"class":311},[294,1486,1377],{"class":1376},[294,1488,1380],{"class":311},[294,1490,1279],{"class":1195},[294,1492,1282],{"class":311},[294,1494,1495,1498,1500],{"class":296,"line":529},[294,1496,1497],{"class":311},"        builder.",[294,1499,1418],{"class":1112},[294,1501,1232],{"class":311},[294,1503,1504,1507,1510,1512,1515],{"class":296,"line":537},[294,1505,1506],{"class":311},"          id: provider.",[294,1508,1509],{"class":1112},"like",[294,1511,1270],{"class":311},[294,1513,1514],{"class":336},"'f47ac10b-58cc-4372-a567-0e02b2c3d479'",[294,1516,1517],{"class":311},"),\n",[294,1519,1520,1523,1526],{"class":296,"line":548},[294,1521,1522],{"class":311},"          status: ",[294,1524,1525],{"class":336},"'confirmed'",[294,1527,1243],{"class":311},[294,1529,1530,1533,1535],{"class":296,"line":556},[294,1531,1532],{"class":311},"          serviceType: ",[294,1534,1428],{"class":336},[294,1536,1243],{"class":311},[294,1538,1539,1542,1544],{"class":296,"line":566},[294,1540,1541],{"class":311},"          dateTime: ",[294,1543,1438],{"class":336},[294,1545,1243],{"class":311},[294,1547,1548],{"class":296,"line":573},[294,1549,1550],{"class":311},"        });\n",[294,1552,1553],{"class":296,"line":580},[294,1554,1470],{"class":311},[294,1556,1557,1559,1562,1564,1566,1569,1572,1574,1576],{"class":296,"line":587},[294,1558,1318],{"class":311},[294,1560,1561],{"class":1112},"executeTest",[294,1563,1270],{"class":311},[294,1565,1298],{"class":1195},[294,1567,1568],{"class":311}," (",[294,1570,1571],{"class":1376},"mockServer",[294,1573,1380],{"class":311},[294,1575,1279],{"class":1195},[294,1577,1282],{"class":311},[294,1579,1580,1583,1586,1588,1591,1594],{"class":296,"line":597},[294,1581,1582],{"class":1195},"        const",[294,1584,1585],{"class":315}," response",[294,1587,1223],{"class":1195},[294,1589,1590],{"class":1195}," await",[294,1592,1593],{"class":1112}," createBooking",[294,1595,1596],{"class":311},"(mockServer.url, {\n",[294,1598,1599,1601,1603],{"class":296,"line":605},[294,1600,1532],{"class":311},[294,1602,1428],{"class":336},[294,1604,1243],{"class":311},[294,1606,1607,1609,1611],{"class":296,"line":615},[294,1608,1541],{"class":311},[294,1610,1438],{"class":336},[294,1612,1243],{"class":311},[294,1614,1615,1618,1620],{"class":296,"line":622},[294,1616,1617],{"class":311},"          customerName: ",[294,1619,1448],{"class":336},[294,1621,1243],{"class":311},[294,1623,1624,1627,1629],{"class":296,"line":629},[294,1625,1626],{"class":311},"          customerEmail: ",[294,1628,1458],{"class":336},[294,1630,1243],{"class":311},[294,1632,1633],{"class":296,"line":636},[294,1634,1550],{"class":311},[294,1636,1637,1640,1643,1646,1648,1650],{"class":296,"line":646},[294,1638,1639],{"class":1112},"        expect",[294,1641,1642],{"class":311},"(response.status).",[294,1644,1645],{"class":1112},"toBe",[294,1647,1270],{"class":311},[294,1649,1525],{"class":336},[294,1651,1652],{"class":311},");\n",[294,1654,1655],{"class":296,"line":651},[294,1656,1657],{"class":311},"      });\n",[294,1659,1660],{"class":296,"line":659},[294,1661,1662],{"class":311},"  });\n",[294,1664,1665],{"class":296,"line":667},[294,1666,1258],{"class":311},[19,1668,1669],{},"The consumer team writes these contract tests. The provider team runs them in their CI pipeline. If a backend change would break a consumer's expectations, the build fails before the change reaches production.",[79,1671,1673],{"id":1672},"api-versioning-strategies","API Versioning Strategies",[19,1675,1676],{},"APIs evolve. Versioning ensures that existing consumers continue to work while new consumers benefit from improvements. There are three common strategies:",[19,1678,1679,1568,1682,1295,1685,1688],{},[23,1680,1681],{},"URL path versioning",[291,1683,1684],{},"/v1/bookings",[291,1686,1687],{},"/v2/bookings","): The simplest and most explicit approach. Easy to route, easy to understand, easy to deprecate. This is what we recommend for most REST APIs.",[19,1690,1691,1568,1694,1697],{},[23,1692,1693],{},"Header versioning",[291,1695,1696],{},"Accept: application/vnd.api.v2+json","): Keeps URLs clean but is harder to discover and test. Better suited for APIs with sophisticated consumers.",[19,1699,1700,1568,1703,1706],{},[23,1701,1702],{},"Query parameter versioning",[291,1704,1705],{},"/bookings?version=2","): Rarely recommended. It conflates versioning with filtering and creates confusing cache behaviour.",[19,1708,1709],{},"Regardless of strategy, follow these rules:",[1711,1712,1713,1716,1719,1722],"ul",{},[50,1714,1715],{},"Never break an existing version without a deprecation period",[50,1717,1718],{},"Version the entire API, not individual endpoints",[50,1720,1721],{},"Provide migration guides for every major version bump",[50,1723,1724],{},"Monitor usage of deprecated versions and communicate sunset timelines",[79,1726,1728],{"id":1727},"rate-limiting-and-security","Rate Limiting and Security",[19,1730,1731],{},"Every production API needs rate limiting and authentication. These are not optional — they are requirements.",[284,1733,1735],{"className":1181,"code":1734,"language":1183,"meta":289,"style":289},"// Rate limiting middleware example (Express/H3)\nimport { createRateLimiter } from './middleware/rate-limiter';\n\nconst apiRateLimiter = createRateLimiter({\n  windowMs: 60 * 1000, // 1 minute\n  maxRequests: 100,     // 100 requests per window\n  keyGenerator: (req) => req.headers['x-api-key'] || req.ip,\n  onLimitReached: (req, res) => {\n    res.status(429).json({\n      error: 'rate_limit_exceeded',\n      message: 'Too many requests. Please retry after the window resets.',\n      retryAfter: res.getHeader('Retry-After'),\n    });\n  },\n});\n",[291,1736,1737,1742,1756,1760,1774,1793,1807,1837,1857,1878,1888,1898,1913,1918,1923],{"__ignoreMap":289},[294,1738,1739],{"class":296,"line":297},[294,1740,1741],{"class":300},"// Rate limiting middleware example (Express/H3)\n",[294,1743,1744,1746,1749,1751,1754],{"class":296,"line":304},[294,1745,1196],{"class":1195},[294,1747,1748],{"class":311}," { createRateLimiter } ",[294,1750,1202],{"class":1195},[294,1752,1753],{"class":336}," './middleware/rate-limiter'",[294,1755,1208],{"class":311},[294,1757,1758],{"class":296,"line":319},[294,1759,366],{"emptyLinePlaceholder":365},[294,1761,1762,1764,1767,1769,1772],{"class":296,"line":328},[294,1763,1217],{"class":1195},[294,1765,1766],{"class":315}," apiRateLimiter",[294,1768,1223],{"class":1195},[294,1770,1771],{"class":1112}," createRateLimiter",[294,1773,1232],{"class":311},[294,1775,1776,1779,1782,1785,1788,1790],{"class":296,"line":340},[294,1777,1778],{"class":311},"  windowMs: ",[294,1780,1781],{"class":315},"60",[294,1783,1784],{"class":1195}," *",[294,1786,1787],{"class":315}," 1000",[294,1789,1295],{"class":311},[294,1791,1792],{"class":300},"// 1 minute\n",[294,1794,1795,1798,1801,1804],{"class":296,"line":351},[294,1796,1797],{"class":311},"  maxRequests: ",[294,1799,1800],{"class":315},"100",[294,1802,1803],{"class":311},",     ",[294,1805,1806],{"class":300},"// 100 requests per window\n",[294,1808,1809,1812,1815,1818,1820,1822,1825,1828,1831,1834],{"class":296,"line":362},[294,1810,1811],{"class":1112},"  keyGenerator",[294,1813,1814],{"class":311},": (",[294,1816,1817],{"class":1376},"req",[294,1819,1380],{"class":311},[294,1821,1279],{"class":1195},[294,1823,1824],{"class":311}," req.headers[",[294,1826,1827],{"class":336},"'x-api-key'",[294,1829,1830],{"class":311},"] ",[294,1832,1833],{"class":1195},"||",[294,1835,1836],{"class":311}," req.ip,\n",[294,1838,1839,1842,1844,1846,1848,1851,1853,1855],{"class":296,"line":369},[294,1840,1841],{"class":1112},"  onLimitReached",[294,1843,1814],{"class":311},[294,1845,1817],{"class":1376},[294,1847,1295],{"class":311},[294,1849,1850],{"class":1376},"res",[294,1852,1380],{"class":311},[294,1854,1279],{"class":1195},[294,1856,1282],{"class":311},[294,1858,1859,1862,1865,1867,1870,1873,1876],{"class":296,"line":377},[294,1860,1861],{"class":311},"    res.",[294,1863,1864],{"class":1112},"status",[294,1866,1270],{"class":311},[294,1868,1869],{"class":315},"429",[294,1871,1872],{"class":311},").",[294,1874,1875],{"class":1112},"json",[294,1877,1232],{"class":311},[294,1879,1880,1883,1886],{"class":296,"line":385},[294,1881,1882],{"class":311},"      error: ",[294,1884,1885],{"class":336},"'rate_limit_exceeded'",[294,1887,1243],{"class":311},[294,1889,1890,1893,1896],{"class":296,"line":393},[294,1891,1892],{"class":311},"      message: ",[294,1894,1895],{"class":336},"'Too many requests. Please retry after the window resets.'",[294,1897,1243],{"class":311},[294,1899,1900,1903,1906,1908,1911],{"class":296,"line":404},[294,1901,1902],{"class":311},"      retryAfter: res.",[294,1904,1905],{"class":1112},"getHeader",[294,1907,1270],{"class":311},[294,1909,1910],{"class":336},"'Retry-After'",[294,1912,1517],{"class":311},[294,1914,1915],{"class":296,"line":415},[294,1916,1917],{"class":311},"    });\n",[294,1919,1920],{"class":296,"line":423},[294,1921,1922],{"class":311},"  },\n",[294,1924,1925],{"class":296,"line":432},[294,1926,1258],{"class":311},[19,1928,1929],{},"For authentication, the choice between API keys, OAuth 2.0, and JWT depends on your consumer types:",[1711,1931,1932,1938,1944],{},[50,1933,1934,1937],{},[23,1935,1936],{},"API keys",": Simple, suitable for server-to-server communication where the consumer is trusted.",[50,1939,1940,1943],{},[23,1941,1942],{},"OAuth 2.0",": Required when third-party applications need delegated access to user data. The authorization code flow with PKCE is the current standard for mobile and web applications.",[50,1945,1946,1949],{},[23,1947,1948],{},"JWT (JSON Web Tokens)",": Efficient for stateless authentication in microservice architectures. Short-lived access tokens with refresh token rotation provide security without constant database lookups.",[1162,1951,1952],{"type":322},[19,1953,1954],{},"API security is not just authentication. It includes input validation, output encoding, CORS configuration, request size limits, and protection against common attacks (injection, BOLA, mass assignment). The OWASP API Security Top 10 is required reading for any team building production APIs.",[14,1956,1958],{"id":1957},"api-documentation-as-a-product","API Documentation as a Product",[19,1960,1961],{},"An API without good documentation is an API nobody will use. Treat your documentation as a product with its own quality standards, user experience, and maintenance schedule.",[79,1963,1965],{"id":1964},"what-great-api-documentation-includes","What Great API Documentation Includes",[1711,1967,1968,1974,1980,1986,1992,1998,2004],{},[50,1969,1970,1973],{},[23,1971,1972],{},"Getting started guide",": A developer should be able to make their first successful API call within 5 minutes of reading your documentation.",[50,1975,1976,1979],{},[23,1977,1978],{},"Authentication guide",": Clear instructions for obtaining and using credentials, with copy-paste examples.",[50,1981,1982,1985],{},[23,1983,1984],{},"Interactive reference",": Every endpoint documented with try-it-out functionality. Tools like Stoplight, Redocly, and Scalar generate these from OpenAPI specifications.",[50,1987,1988,1991],{},[23,1989,1990],{},"Code examples",": In every language your consumers use. At minimum: JavaScript, Python, and cURL.",[50,1993,1994,1997],{},[23,1995,1996],{},"Error reference",": Every possible error code documented with the cause and the recommended resolution.",[50,1999,2000,2003],{},[23,2001,2002],{},"Changelog",": What changed in each version, with migration instructions for breaking changes.",[50,2005,2006,2009],{},[23,2007,2008],{},"SDKs and client libraries",": Auto-generated from your OpenAPI specification and published to npm, PyPI, and other package registries.",[19,2011,2012,2013,2017],{},"For businesses building ",[230,2014,2016],{"href":2015},"/solutions/cloud-native","cloud-native platforms",", a developer portal with interactive API documentation is not a nice-to-have — it is a competitive advantage. Partners and developers choose platforms that are easy to integrate with.",[14,2019,2021],{"id":2020},"common-mistakes-to-avoid","Common Mistakes to Avoid",[19,2023,2024],{},"After designing and reviewing dozens of APIs, we see the same mistakes repeatedly. Here are the most damaging ones.",[79,2026,2028],{"id":2027},"designing-apis-around-database-schemas","Designing APIs Around Database Schemas",[19,2030,2031],{},"Your API should model your business domain, not your database tables. If your API response mirrors a database JOIN with nested foreign keys and auto-increment IDs, you have coupled your public interface to your internal implementation. Every database migration becomes a potential breaking API change.",[79,2033,2035],{"id":2034},"inconsistent-naming-conventions","Inconsistent Naming Conventions",[19,2037,2038,2039,2042,2043,2046,2047,2050],{},"Pick a convention and enforce it everywhere. If you use ",[291,2040,2041],{},"camelCase"," for property names, use it consistently across every endpoint. If you use plural nouns for collection resources (",[291,2044,2045],{},"/bookings",", not ",[291,2048,2049],{},"/booking","), do not suddenly switch to singular elsewhere. Inconsistency forces consumers to guess, which means bugs.",[79,2052,2054],{"id":2053},"missing-pagination","Missing Pagination",[19,2056,2057],{},"Any endpoint that returns a list will eventually return a list too large to process in a single response. Design pagination into your list endpoints from day one — even if your current dataset is small.",[284,2059,2061],{"className":1181,"code":2060,"language":1183,"meta":289,"style":289},"// Cursor-based pagination response\ninterface PaginatedResponse\u003CT> {\n  data: T[];\n  pagination: {\n    cursor: string | null;\n    hasMore: boolean;\n    totalCount: number;\n  };\n}\n\n// Usage: GET /bookings?cursor=abc123&limit=25\n",[291,2062,2063,2068,2085,2099,2108,2126,2138,2150,2155,2160,2164],{"__ignoreMap":289},[294,2064,2065],{"class":296,"line":297},[294,2066,2067],{"class":300},"// Cursor-based pagination response\n",[294,2069,2070,2073,2076,2079,2082],{"class":296,"line":304},[294,2071,2072],{"class":1195},"interface",[294,2074,2075],{"class":1112}," PaginatedResponse",[294,2077,2078],{"class":311},"\u003C",[294,2080,2081],{"class":1112},"T",[294,2083,2084],{"class":311},"> {\n",[294,2086,2087,2090,2093,2096],{"class":296,"line":319},[294,2088,2089],{"class":1376},"  data",[294,2091,2092],{"class":1195},":",[294,2094,2095],{"class":1112}," T",[294,2097,2098],{"class":311},"[];\n",[294,2100,2101,2104,2106],{"class":296,"line":328},[294,2102,2103],{"class":1376},"  pagination",[294,2105,2092],{"class":1195},[294,2107,1282],{"class":311},[294,2109,2110,2113,2115,2118,2121,2124],{"class":296,"line":340},[294,2111,2112],{"class":1376},"    cursor",[294,2114,2092],{"class":1195},[294,2116,2117],{"class":315}," string",[294,2119,2120],{"class":1195}," |",[294,2122,2123],{"class":315}," null",[294,2125,1208],{"class":311},[294,2127,2128,2131,2133,2136],{"class":296,"line":351},[294,2129,2130],{"class":1376},"    hasMore",[294,2132,2092],{"class":1195},[294,2134,2135],{"class":315}," boolean",[294,2137,1208],{"class":311},[294,2139,2140,2143,2145,2148],{"class":296,"line":362},[294,2141,2142],{"class":1376},"    totalCount",[294,2144,2092],{"class":1195},[294,2146,2147],{"class":315}," number",[294,2149,1208],{"class":311},[294,2151,2152],{"class":296,"line":369},[294,2153,2154],{"class":311},"  };\n",[294,2156,2157],{"class":296,"line":377},[294,2158,2159],{"class":311},"}\n",[294,2161,2162],{"class":296,"line":385},[294,2163,366],{"emptyLinePlaceholder":365},[294,2165,2166],{"class":296,"line":393},[294,2167,2168],{"class":300},"// Usage: GET /bookings?cursor=abc123&limit=25\n",[19,2170,2171],{},"Cursor-based pagination is preferred over offset-based for production APIs. It handles insertions and deletions gracefully and performs better on large datasets.",[79,2173,2175],{"id":2174},"breaking-changes-without-versioning","Breaking Changes Without Versioning",[19,2177,2178,2179,2183],{},"Adding a new optional field to a response is not a breaking change. Removing a field, changing a field's type, or altering error response formats ",[2180,2181,2182],"em",{},"are"," breaking changes. If you do not version your API, every breaking change becomes an incident for every consumer simultaneously.",[79,2185,2187],{"id":2186},"ignoring-error-design","Ignoring Error Design",[19,2189,2190,2191,2194],{},"Generic ",[291,2192,2193],{},"500 Internal Server Error"," responses are not acceptable. Every error should include a machine-readable error code, a human-readable message, and enough context for the consumer to take corrective action.",[284,2196,2199],{"className":2197,"code":2198,"language":1875,"meta":289,"style":289},"language-json shiki shiki-themes github-light github-dark","{\n  \"error\": {\n    \"code\": \"BOOKING_SLOT_UNAVAILABLE\",\n    \"message\": \"The requested time slot is no longer available.\",\n    \"details\": {\n      \"requestedDateTime\": \"2026-02-17T14:30:00Z\",\n      \"nextAvailableSlots\": [\n        \"2026-02-17T15:00:00Z\",\n        \"2026-02-17T16:30:00Z\",\n        \"2026-02-18T09:00:00Z\"\n      ]\n    }\n  }\n}\n",[291,2200,2201,2206,2214,2226,2238,2245,2257,2265,2272,2279,2284,2289,2294,2299],{"__ignoreMap":289},[294,2202,2203],{"class":296,"line":297},[294,2204,2205],{"class":311},"{\n",[294,2207,2208,2211],{"class":296,"line":304},[294,2209,2210],{"class":315},"  \"error\"",[294,2212,2213],{"class":311},": {\n",[294,2215,2216,2219,2221,2224],{"class":296,"line":319},[294,2217,2218],{"class":315},"    \"code\"",[294,2220,312],{"class":311},[294,2222,2223],{"class":336},"\"BOOKING_SLOT_UNAVAILABLE\"",[294,2225,1243],{"class":311},[294,2227,2228,2231,2233,2236],{"class":296,"line":328},[294,2229,2230],{"class":315},"    \"message\"",[294,2232,312],{"class":311},[294,2234,2235],{"class":336},"\"The requested time slot is no longer available.\"",[294,2237,1243],{"class":311},[294,2239,2240,2243],{"class":296,"line":340},[294,2241,2242],{"class":315},"    \"details\"",[294,2244,2213],{"class":311},[294,2246,2247,2250,2252,2255],{"class":296,"line":351},[294,2248,2249],{"class":315},"      \"requestedDateTime\"",[294,2251,312],{"class":311},[294,2253,2254],{"class":336},"\"2026-02-17T14:30:00Z\"",[294,2256,1243],{"class":311},[294,2258,2259,2262],{"class":296,"line":362},[294,2260,2261],{"class":315},"      \"nextAvailableSlots\"",[294,2263,2264],{"class":311},": [\n",[294,2266,2267,2270],{"class":296,"line":369},[294,2268,2269],{"class":336},"        \"2026-02-17T15:00:00Z\"",[294,2271,1243],{"class":311},[294,2273,2274,2277],{"class":296,"line":377},[294,2275,2276],{"class":336},"        \"2026-02-17T16:30:00Z\"",[294,2278,1243],{"class":311},[294,2280,2281],{"class":296,"line":385},[294,2282,2283],{"class":336},"        \"2026-02-18T09:00:00Z\"\n",[294,2285,2286],{"class":296,"line":393},[294,2287,2288],{"class":311},"      ]\n",[294,2290,2291],{"class":296,"line":404},[294,2292,2293],{"class":311},"    }\n",[294,2295,2296],{"class":296,"line":415},[294,2297,2298],{"class":311},"  }\n",[294,2300,2301],{"class":296,"line":423},[294,2302,2159],{"class":311},[19,2304,2305],{},"This error response tells the consumer exactly what went wrong and what to do next. It transforms an error from a dead end into a continuation of the user flow.",[14,2307,2309],{"id":2308},"getting-started-with-api-first","Getting Started with API-First",[19,2311,2312],{},"If your organisation currently follows a code-first approach, transitioning to API-first does not require a big-bang migration. Start with your next new service or feature:",[47,2314,2315,2321,2327,2333,2339],{},[50,2316,2317,2320],{},[23,2318,2319],{},"Write the OpenAPI specification first."," Before any implementation code. Share it with all stakeholders for review.",[50,2322,2323,2326],{},[23,2324,2325],{},"Generate mock servers."," Let frontend and mobile teams start building immediately.",[50,2328,2329,2332],{},[23,2330,2331],{},"Implement the backend against the specification."," The spec is the acceptance criteria.",[50,2334,2335,2338],{},[23,2336,2337],{},"Add contract tests to your CI pipeline."," Catch specification drift automatically.",[50,2340,2341,2344],{},[23,2342,2343],{},"Publish interactive documentation."," Make it easy for everyone to understand and use the API.",[19,2346,2347],{},"Once your team experiences the speed and reliability of API-first development on one project, the approach tends to spread organically. Teams that have worked this way rarely want to go back.",[19,2349,2350,2351,2355],{},"For organisations with existing APIs that need restructuring, a ",[230,2352,2354],{"href":2353},"/solutions/web-development","web development engagement"," can help you introduce API-first practices incrementally — redesigning your most critical APIs first and building the tooling and workflows that make the approach sustainable.",[2357,2358],"hr",{},[19,2360,2361],{},[2180,2362,2363,2364,2368],{},"Need to design or rebuild your API layer? ",[230,2365,2367],{"href":2366},"/contact","Talk to our integration engineering team"," about building APIs that scale with your business.",[2370,2371,2372],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":289,"searchDepth":304,"depth":304,"links":2374},[2375,2376,2377,2382,2388,2395,2398,2405],{"id":16,"depth":304,"text":17},{"id":38,"depth":304,"text":39},{"id":73,"depth":304,"text":74,"children":2378},[2379,2380,2381],{"id":81,"depth":319,"text":82},{"id":97,"depth":319,"text":98},{"id":111,"depth":319,"text":112},{"id":214,"depth":304,"text":215,"children":2383},[2384,2385,2386,2387],{"id":221,"depth":319,"text":222},{"id":237,"depth":319,"text":238},{"id":244,"depth":319,"text":245},{"id":264,"depth":319,"text":265},{"id":271,"depth":304,"text":272,"children":2389},[2390,2391,2392,2393,2394],{"id":278,"depth":319,"text":279},{"id":1091,"depth":319,"text":1092},{"id":1174,"depth":319,"text":1175},{"id":1672,"depth":319,"text":1673},{"id":1727,"depth":319,"text":1728},{"id":1957,"depth":304,"text":1958,"children":2396},[2397],{"id":1964,"depth":319,"text":1965},{"id":2020,"depth":304,"text":2021,"children":2399},[2400,2401,2402,2403,2404],{"id":2027,"depth":319,"text":2028},{"id":2034,"depth":319,"text":2035},{"id":2053,"depth":319,"text":2054},{"id":2174,"depth":319,"text":2175},{"id":2186,"depth":319,"text":2187},{"id":2308,"depth":304,"text":2309},"Engineering",null,"2026-02-10","API-first development is reshaping how companies build software. Learn the principles, benefits, and implementation patterns behind this modern approach.","md",false,{},"/blog/api-first-approach-guide","9 min read",{"title":6,"description":2409},"blog/api-first-approach-guide",[2418,141,2419,2420],"API Development","Microservices","Integration","-bqCOEq9ROQy5sCtOFK8kGYzyEJA6yDyJnG38FiWNH4",{"id":2423,"title":2424,"author":2425,"body":2428,"category":3613,"coverImage":2407,"date":3614,"description":3615,"extension":2410,"featured":365,"meta":3616,"navigation":365,"path":3617,"readingTime":3618,"seo":3619,"stem":3620,"tags":3621,"__hash__":3625},"blog/blog/building-connekz-ai-agent.md","Inside Connekz: How We Built an AI Agent That Books, Sells, and Supports",{"name":2426,"role":2427},"Amaya Perera","Head of AI & Machine Learning",{"type":11,"value":2429,"toc":3587},[2430,2434,2440,2443,2448,2452,2455,2459,2462,2466,2469,2473,2476,2479,2483,2486,2489,2515,2837,2842,2846,2849,2852,2856,2859,2863,2866,3177,3181,3184,3187,3252,3255,3260,3264,3267,3271,3274,3278,3285,3289,3292,3296,3299,3325,3329,3332,3335,3355,3358,3362,3365,3368,3382,3385,3389,3392,3424,3427,3431,3434,3517,3524,3533,3537,3540,3570,3573,3575,3584],[14,2431,2433],{"id":2432},"why-we-built-connekz","Why We Built Connekz",[19,2435,2436,2437,2439],{},"Most businesses cannot afford a 24/7 sales and support team, yet their customers expect instant, intelligent responses at any hour. ",[23,2438,252],{}," is the AI agent platform we built to bridge that gap — a system that does not just answer questions, but takes real-world actions: booking appointments, checking availability, processing orders, and updating CRM records, all through natural conversation.",[19,2441,2442],{},"This is the story of how we designed, built, and scaled Connekz from an internal prototype to a production platform serving businesses across New Zealand and beyond. We will cover the architecture decisions, the hard engineering problems, and the lessons we learned shipping AI agents into high-stakes customer-facing environments.",[31,2444,2445],{},[19,2446,2447],{},"Building an AI chatbot is easy. Building an AI agent that businesses trust with their customers and revenue is a fundamentally different problem.",[14,2449,2451],{"id":2450},"the-problem-we-set-out-to-solve","The Problem We Set Out to Solve",[19,2453,2454],{},"Before building Connekz, we spent months interviewing business owners across industries — healthcare clinics, trade services, hospitality, professional services. Three problems appeared consistently.",[79,2456,2458],{"id":2457},"lost-leads-outside-business-hours","Lost leads outside business hours",[19,2460,2461],{},"A physiotherapy clinic we worked with tracked their missed calls. Forty-two percent of new patient enquiries came outside business hours. Every one of those was a potential booking lost to a competitor who answered the phone. Multiplied across hundreds of businesses, the scale of lost revenue was staggering.",[79,2463,2465],{"id":2464},"overwhelmed-support-teams","Overwhelmed support teams",[19,2467,2468],{},"A mid-sized e-commerce company had three customer support staff handling 200+ daily enquiries. Seventy percent of those enquiries were repetitive — order status checks, return policy questions, product availability. The team spent most of their day answering the same questions, leaving complex issues waiting in queue.",[79,2470,2472],{"id":2471},"inconsistent-customer-experiences","Inconsistent customer experiences",[19,2474,2475],{},"When a business operates across multiple channels — phone, email, website chat, social media — customers receive different levels of service depending on which channel they use and which team member responds. Tone, accuracy, and response time vary wildly. There is no single source of truth for how the business should communicate.",[19,2477,2478],{},"Connekz was designed to solve all three problems simultaneously. Not by replacing human teams, but by handling the predictable, repetitive interactions so that human staff can focus on the complex, high-value conversations where they make the biggest difference.",[79,2480,2482],{"id":2481},"rag-pipeline-for-business-specific-knowledge","RAG Pipeline for Business-Specific Knowledge",[19,2484,2485],{},"Every business that deploys Connekz has unique products, services, policies, and terminology. We use Retrieval-Augmented Generation (RAG) to ground the AI agent in business-specific knowledge without fine-tuning a model for each customer.",[19,2487,2488],{},"The RAG pipeline works as follows:",[47,2490,2491,2497,2503,2509],{},[50,2492,2493,2496],{},[23,2494,2495],{},"Ingestion",": Business documents — product catalogues, service descriptions, FAQs, policies, pricing — are processed, chunked, and embedded into a vector database.",[50,2498,2499,2502],{},[23,2500,2501],{},"Retrieval",": When a customer asks a question, the system retrieves the most relevant document chunks based on semantic similarity.",[50,2504,2505,2508],{},[23,2506,2507],{},"Augmented generation",": Retrieved context is injected into the model's prompt alongside the conversation history, grounding the response in verified business information.",[50,2510,2511,2514],{},[23,2512,2513],{},"Citation tracking",": Every factual claim in a response is linked back to its source document, enabling audit trails and accuracy verification.",[284,2516,2518],{"className":1181,"code":2517,"language":1183,"meta":289,"style":289},"// Simplified RAG retrieval pipeline\ninterface RetrievedChunk {\n  content: string;\n  source: string;\n  relevanceScore: number;\n  metadata: Record\u003Cstring, unknown>;\n}\n\nasync function retrieveContext(\n  query: string,\n  businessId: string,\n  topK: number = 5,\n): Promise\u003CRetrievedChunk[]> {\n  const embedding = await embedQuery(query);\n\n  const results = await vectorDb.search({\n    collection: `business_${businessId}`,\n    vector: embedding,\n    topK,\n    filter: { active: true },\n  });\n\n  return results\n    .filter((r) => r.relevanceScore > 0.75)\n    .map((r) => ({\n      content: r.payload.content,\n      source: r.payload.source,\n      relevanceScore: r.score,\n      metadata: r.payload.metadata,\n    }));\n}\n",[291,2519,2520,2525,2534,2545,2556,2567,2590,2594,2598,2611,2622,2633,2649,2667,2685,2689,2708,2724,2729,2734,2745,2749,2753,2761,2790,2808,2813,2818,2823,2828,2833],{"__ignoreMap":289},[294,2521,2522],{"class":296,"line":297},[294,2523,2524],{"class":300},"// Simplified RAG retrieval pipeline\n",[294,2526,2527,2529,2532],{"class":296,"line":304},[294,2528,2072],{"class":1195},[294,2530,2531],{"class":1112}," RetrievedChunk",[294,2533,1282],{"class":311},[294,2535,2536,2539,2541,2543],{"class":296,"line":319},[294,2537,2538],{"class":1376},"  content",[294,2540,2092],{"class":1195},[294,2542,2117],{"class":315},[294,2544,1208],{"class":311},[294,2546,2547,2550,2552,2554],{"class":296,"line":328},[294,2548,2549],{"class":1376},"  source",[294,2551,2092],{"class":1195},[294,2553,2117],{"class":315},[294,2555,1208],{"class":311},[294,2557,2558,2561,2563,2565],{"class":296,"line":340},[294,2559,2560],{"class":1376},"  relevanceScore",[294,2562,2092],{"class":1195},[294,2564,2147],{"class":315},[294,2566,1208],{"class":311},[294,2568,2569,2572,2574,2577,2579,2582,2584,2587],{"class":296,"line":351},[294,2570,2571],{"class":1376},"  metadata",[294,2573,2092],{"class":1195},[294,2575,2576],{"class":1112}," Record",[294,2578,2078],{"class":311},[294,2580,2581],{"class":315},"string",[294,2583,1295],{"class":311},[294,2585,2586],{"class":315},"unknown",[294,2588,2589],{"class":311},">;\n",[294,2591,2592],{"class":296,"line":362},[294,2593,2159],{"class":311},[294,2595,2596],{"class":296,"line":369},[294,2597,366],{"emptyLinePlaceholder":365},[294,2599,2600,2602,2605,2608],{"class":296,"line":377},[294,2601,1298],{"class":1195},[294,2603,2604],{"class":1195}," function",[294,2606,2607],{"class":1112}," retrieveContext",[294,2609,2610],{"class":311},"(\n",[294,2612,2613,2616,2618,2620],{"class":296,"line":385},[294,2614,2615],{"class":1376},"  query",[294,2617,2092],{"class":1195},[294,2619,2117],{"class":315},[294,2621,1243],{"class":311},[294,2623,2624,2627,2629,2631],{"class":296,"line":393},[294,2625,2626],{"class":1376},"  businessId",[294,2628,2092],{"class":1195},[294,2630,2117],{"class":315},[294,2632,1243],{"class":311},[294,2634,2635,2638,2640,2642,2644,2647],{"class":296,"line":404},[294,2636,2637],{"class":1376},"  topK",[294,2639,2092],{"class":1195},[294,2641,2147],{"class":315},[294,2643,1223],{"class":1195},[294,2645,2646],{"class":315}," 5",[294,2648,1243],{"class":311},[294,2650,2651,2654,2656,2659,2661,2664],{"class":296,"line":415},[294,2652,2653],{"class":311},")",[294,2655,2092],{"class":1195},[294,2657,2658],{"class":1112}," Promise",[294,2660,2078],{"class":311},[294,2662,2663],{"class":1112},"RetrievedChunk",[294,2665,2666],{"class":311},"[]> {\n",[294,2668,2669,2672,2675,2677,2679,2682],{"class":296,"line":423},[294,2670,2671],{"class":1195},"  const",[294,2673,2674],{"class":315}," embedding",[294,2676,1223],{"class":1195},[294,2678,1590],{"class":1195},[294,2680,2681],{"class":1112}," embedQuery",[294,2683,2684],{"class":311},"(query);\n",[294,2686,2687],{"class":296,"line":432},[294,2688,366],{"emptyLinePlaceholder":365},[294,2690,2691,2693,2696,2698,2700,2703,2706],{"class":296,"line":440},[294,2692,2671],{"class":1195},[294,2694,2695],{"class":315}," results",[294,2697,1223],{"class":1195},[294,2699,1590],{"class":1195},[294,2701,2702],{"class":311}," vectorDb.",[294,2704,2705],{"class":1112},"search",[294,2707,1232],{"class":311},[294,2709,2710,2713,2716,2719,2722],{"class":296,"line":451},[294,2711,2712],{"class":311},"    collection: ",[294,2714,2715],{"class":336},"`business_${",[294,2717,2718],{"class":311},"businessId",[294,2720,2721],{"class":336},"}`",[294,2723,1243],{"class":311},[294,2725,2726],{"class":296,"line":459},[294,2727,2728],{"class":311},"    vector: embedding,\n",[294,2730,2731],{"class":296,"line":467},[294,2732,2733],{"class":311},"    topK,\n",[294,2735,2736,2739,2742],{"class":296,"line":475},[294,2737,2738],{"class":311},"    filter: { active: ",[294,2740,2741],{"class":315},"true",[294,2743,2744],{"class":311}," },\n",[294,2746,2747],{"class":296,"line":486},[294,2748,1662],{"class":311},[294,2750,2751],{"class":296,"line":494},[294,2752,366],{"emptyLinePlaceholder":365},[294,2754,2755,2758],{"class":296,"line":502},[294,2756,2757],{"class":1195},"  return",[294,2759,2760],{"class":311}," results\n",[294,2762,2763,2766,2769,2772,2775,2777,2779,2782,2785,2788],{"class":296,"line":513},[294,2764,2765],{"class":311},"    .",[294,2767,2768],{"class":1112},"filter",[294,2770,2771],{"class":311},"((",[294,2773,2774],{"class":1376},"r",[294,2776,1380],{"class":311},[294,2778,1279],{"class":1195},[294,2780,2781],{"class":311}," r.relevanceScore ",[294,2783,2784],{"class":1195},">",[294,2786,2787],{"class":315}," 0.75",[294,2789,1339],{"class":311},[294,2791,2792,2794,2797,2799,2801,2803,2805],{"class":296,"line":521},[294,2793,2765],{"class":311},[294,2795,2796],{"class":1112},"map",[294,2798,2771],{"class":311},[294,2800,2774],{"class":1376},[294,2802,1380],{"class":311},[294,2804,1279],{"class":1195},[294,2806,2807],{"class":311}," ({\n",[294,2809,2810],{"class":296,"line":529},[294,2811,2812],{"class":311},"      content: r.payload.content,\n",[294,2814,2815],{"class":296,"line":537},[294,2816,2817],{"class":311},"      source: r.payload.source,\n",[294,2819,2820],{"class":296,"line":548},[294,2821,2822],{"class":311},"      relevanceScore: r.score,\n",[294,2824,2825],{"class":296,"line":556},[294,2826,2827],{"class":311},"      metadata: r.payload.metadata,\n",[294,2829,2830],{"class":296,"line":566},[294,2831,2832],{"class":311},"    }));\n",[294,2834,2835],{"class":296,"line":573},[294,2836,2159],{"class":311},[1162,2838,2839],{"type":322},[19,2840,2841],{},"RAG is not a magic bullet. The quality of retrieved context depends entirely on the quality of the source documents. We invest significant effort in helping clients structure and clean their knowledge base before deployment.",[79,2843,2845],{"id":2844},"voice-and-text-modes","Voice and Text Modes",[19,2847,2848],{},"Connekz operates in both text and voice modes. Text mode powers web chat widgets, WhatsApp integrations, and SMS interactions. Voice mode handles phone calls through real-time speech-to-text, agent processing, and text-to-speech.",[19,2850,2851],{},"Voice introduces additional engineering challenges: turn-taking (knowing when the caller has finished speaking), barge-in handling (the caller interrupts the agent mid-response), and latency requirements (voice conversations feel unnatural if response time exceeds 1.5 seconds).",[14,2853,2855],{"id":2854},"the-tool-calling-system-how-connekz-takes-action","The Tool-Calling System: How Connekz Takes Action",[19,2857,2858],{},"The defining feature that separates Connekz from a standard chatbot is its ability to take real-world actions. When a customer says \"I'd like to book an appointment for next Tuesday,\" Connekz does not just acknowledge the request — it checks the calendar, finds available slots, and creates the booking.",[79,2860,2862],{"id":2861},"how-tool-calling-works","How Tool Calling Works",[19,2864,2865],{},"The AI model is provided with a set of function definitions describing the actions it can take. Each function definition includes a name, description, and a parameter schema. When the model determines that an action is needed, it generates a structured tool call rather than a text response.",[284,2867,2869],{"className":1181,"code":2868,"language":1183,"meta":289,"style":289},"// Tool definition for appointment booking\nconst bookAppointmentTool = {\n  name: 'book_appointment',\n  description:\n    'Books an appointment for a customer. Use this when the customer wants to schedule a visit, consultation, or service.',\n  parameters: {\n    type: 'object',\n    properties: {\n      service_type: {\n        type: 'string',\n        description: 'The type of service requested',\n        enum: ['consultation', 'follow-up', 'initial-assessment', 'treatment'],\n      },\n      preferred_date: {\n        type: 'string',\n        format: 'date',\n        description: 'The customer preferred date (ISO 8601)',\n      },\n      preferred_time_range: {\n        type: 'string',\n        enum: ['morning', 'afternoon', 'evening'],\n        description: 'Preferred time of day',\n      },\n      customer_name: {\n        type: 'string',\n        description: 'Full name of the customer',\n      },\n      customer_phone: {\n        type: 'string',\n        description: 'Contact phone number',\n      },\n      notes: {\n        type: 'string',\n        description: 'Any additional notes or requirements',\n      },\n    },\n    required: ['service_type', 'preferred_date', 'customer_name'],\n  },\n};\n",[291,2870,2871,2876,2887,2897,2902,2909,2914,2924,2929,2934,2944,2954,2979,2984,2989,2997,3007,3016,3020,3025,3033,3052,3061,3065,3070,3078,3087,3091,3096,3104,3113,3117,3122,3130,3139,3143,3148,3168,3172],{"__ignoreMap":289},[294,2872,2873],{"class":296,"line":297},[294,2874,2875],{"class":300},"// Tool definition for appointment booking\n",[294,2877,2878,2880,2883,2885],{"class":296,"line":304},[294,2879,1217],{"class":1195},[294,2881,2882],{"class":315}," bookAppointmentTool",[294,2884,1223],{"class":1195},[294,2886,1282],{"class":311},[294,2888,2889,2892,2895],{"class":296,"line":319},[294,2890,2891],{"class":311},"  name: ",[294,2893,2894],{"class":336},"'book_appointment'",[294,2896,1243],{"class":311},[294,2898,2899],{"class":296,"line":328},[294,2900,2901],{"class":311},"  description:\n",[294,2903,2904,2907],{"class":296,"line":340},[294,2905,2906],{"class":336},"    'Books an appointment for a customer. Use this when the customer wants to schedule a visit, consultation, or service.'",[294,2908,1243],{"class":311},[294,2910,2911],{"class":296,"line":351},[294,2912,2913],{"class":311},"  parameters: {\n",[294,2915,2916,2919,2922],{"class":296,"line":362},[294,2917,2918],{"class":311},"    type: ",[294,2920,2921],{"class":336},"'object'",[294,2923,1243],{"class":311},[294,2925,2926],{"class":296,"line":369},[294,2927,2928],{"class":311},"    properties: {\n",[294,2930,2931],{"class":296,"line":377},[294,2932,2933],{"class":311},"      service_type: {\n",[294,2935,2936,2939,2942],{"class":296,"line":385},[294,2937,2938],{"class":311},"        type: ",[294,2940,2941],{"class":336},"'string'",[294,2943,1243],{"class":311},[294,2945,2946,2949,2952],{"class":296,"line":393},[294,2947,2948],{"class":311},"        description: ",[294,2950,2951],{"class":336},"'The type of service requested'",[294,2953,1243],{"class":311},[294,2955,2956,2959,2961,2963,2966,2968,2971,2973,2976],{"class":296,"line":404},[294,2957,2958],{"class":311},"        enum: [",[294,2960,1428],{"class":336},[294,2962,1295],{"class":311},[294,2964,2965],{"class":336},"'follow-up'",[294,2967,1295],{"class":311},[294,2969,2970],{"class":336},"'initial-assessment'",[294,2972,1295],{"class":311},[294,2974,2975],{"class":336},"'treatment'",[294,2977,2978],{"class":311},"],\n",[294,2980,2981],{"class":296,"line":415},[294,2982,2983],{"class":311},"      },\n",[294,2985,2986],{"class":296,"line":423},[294,2987,2988],{"class":311},"      preferred_date: {\n",[294,2990,2991,2993,2995],{"class":296,"line":432},[294,2992,2938],{"class":311},[294,2994,2941],{"class":336},[294,2996,1243],{"class":311},[294,2998,2999,3002,3005],{"class":296,"line":440},[294,3000,3001],{"class":311},"        format: ",[294,3003,3004],{"class":336},"'date'",[294,3006,1243],{"class":311},[294,3008,3009,3011,3014],{"class":296,"line":451},[294,3010,2948],{"class":311},[294,3012,3013],{"class":336},"'The customer preferred date (ISO 8601)'",[294,3015,1243],{"class":311},[294,3017,3018],{"class":296,"line":459},[294,3019,2983],{"class":311},[294,3021,3022],{"class":296,"line":467},[294,3023,3024],{"class":311},"      preferred_time_range: {\n",[294,3026,3027,3029,3031],{"class":296,"line":475},[294,3028,2938],{"class":311},[294,3030,2941],{"class":336},[294,3032,1243],{"class":311},[294,3034,3035,3037,3040,3042,3045,3047,3050],{"class":296,"line":486},[294,3036,2958],{"class":311},[294,3038,3039],{"class":336},"'morning'",[294,3041,1295],{"class":311},[294,3043,3044],{"class":336},"'afternoon'",[294,3046,1295],{"class":311},[294,3048,3049],{"class":336},"'evening'",[294,3051,2978],{"class":311},[294,3053,3054,3056,3059],{"class":296,"line":494},[294,3055,2948],{"class":311},[294,3057,3058],{"class":336},"'Preferred time of day'",[294,3060,1243],{"class":311},[294,3062,3063],{"class":296,"line":502},[294,3064,2983],{"class":311},[294,3066,3067],{"class":296,"line":513},[294,3068,3069],{"class":311},"      customer_name: {\n",[294,3071,3072,3074,3076],{"class":296,"line":521},[294,3073,2938],{"class":311},[294,3075,2941],{"class":336},[294,3077,1243],{"class":311},[294,3079,3080,3082,3085],{"class":296,"line":529},[294,3081,2948],{"class":311},[294,3083,3084],{"class":336},"'Full name of the customer'",[294,3086,1243],{"class":311},[294,3088,3089],{"class":296,"line":537},[294,3090,2983],{"class":311},[294,3092,3093],{"class":296,"line":548},[294,3094,3095],{"class":311},"      customer_phone: {\n",[294,3097,3098,3100,3102],{"class":296,"line":556},[294,3099,2938],{"class":311},[294,3101,2941],{"class":336},[294,3103,1243],{"class":311},[294,3105,3106,3108,3111],{"class":296,"line":566},[294,3107,2948],{"class":311},[294,3109,3110],{"class":336},"'Contact phone number'",[294,3112,1243],{"class":311},[294,3114,3115],{"class":296,"line":573},[294,3116,2983],{"class":311},[294,3118,3119],{"class":296,"line":580},[294,3120,3121],{"class":311},"      notes: {\n",[294,3123,3124,3126,3128],{"class":296,"line":587},[294,3125,2938],{"class":311},[294,3127,2941],{"class":336},[294,3129,1243],{"class":311},[294,3131,3132,3134,3137],{"class":296,"line":597},[294,3133,2948],{"class":311},[294,3135,3136],{"class":336},"'Any additional notes or requirements'",[294,3138,1243],{"class":311},[294,3140,3141],{"class":296,"line":605},[294,3142,2983],{"class":311},[294,3144,3145],{"class":296,"line":615},[294,3146,3147],{"class":311},"    },\n",[294,3149,3150,3153,3156,3158,3161,3163,3166],{"class":296,"line":622},[294,3151,3152],{"class":311},"    required: [",[294,3154,3155],{"class":336},"'service_type'",[294,3157,1295],{"class":311},[294,3159,3160],{"class":336},"'preferred_date'",[294,3162,1295],{"class":311},[294,3164,3165],{"class":336},"'customer_name'",[294,3167,2978],{"class":311},[294,3169,3170],{"class":296,"line":629},[294,3171,1922],{"class":311},[294,3173,3174],{"class":296,"line":636},[294,3175,3176],{"class":311},"};\n",[79,3178,3180],{"id":3179},"safety-guardrails-and-confirmation-flows","Safety Guardrails and Confirmation Flows",[19,3182,3183],{},"Tool calls that modify data or create commitments always pass through a confirmation flow. The agent presents the proposed action to the customer and waits for explicit confirmation before executing.",[19,3185,3186],{},"For example, a booking flow looks like this:",[47,3188,3189,3195,3204,3210,3215,3220,3225,3230,3235,3240,3247],{},[50,3190,3191,3194],{},[23,3192,3193],{},"Customer",": \"I'd like to book a consultation for next Tuesday afternoon.\"",[50,3196,3197,3200,3201],{},[23,3198,3199],{},"Agent"," (internal): Calls ",[291,3202,3203],{},"check_availability({ date: '2026-02-17', time_range: 'afternoon' })",[50,3205,3206,3209],{},[23,3207,3208],{},"System",": Returns available slots: 1:00 PM, 2:30 PM, 4:00 PM",[50,3211,3212,3214],{},[23,3213,3199],{},": \"I have three afternoon slots available on Tuesday the 17th: 1:00 PM, 2:30 PM, and 4:00 PM. Which works best for you?\"",[50,3216,3217,3219],{},[23,3218,3193],{},": \"2:30 works.\"",[50,3221,3222,3224],{},[23,3223,3199],{},": \"I'll book you in for a consultation at 2:30 PM on Tuesday 17 February. Could I get your full name and a contact number?\"",[50,3226,3227,3229],{},[23,3228,3193],{},": \"Sarah Chen, 021 555 0123.\"",[50,3231,3232,3234],{},[23,3233,3199],{},": \"To confirm: a consultation for Sarah Chen at 2:30 PM on Tuesday 17 February. I'll send a confirmation to 021 555 0123. Shall I go ahead?\"",[50,3236,3237,3239],{},[23,3238,3193],{},": \"Yes please.\"",[50,3241,3242,3200,3244],{},[23,3243,3199],{},[291,3245,3246],{},"book_appointment({ service_type: 'consultation', preferred_date: '2026-02-17', preferred_time_range: 'afternoon', customer_name: 'Sarah Chen', customer_phone: '021 555 0123' })",[50,3248,3249,3251],{},[23,3250,3199],{},": \"You're all booked in. You'll receive a confirmation text shortly. Is there anything else I can help with?\"",[19,3253,3254],{},"The confirmation step is non-negotiable. The agent never creates a booking, processes a payment, or modifies a record without explicit customer approval.",[1162,3256,3257],{"type":1164},[19,3258,3259],{},"Designing confirmation flows is as important as designing the AI model itself. A single incorrect booking damages trust far more than a slow response time. We err heavily on the side of confirming before acting.",[14,3261,3263],{"id":3262},"multi-platform-deployment","Multi-Platform Deployment",[19,3265,3266],{},"Connekz deploys wherever your customers are. Each deployment mode is optimised for its platform while sharing the same core intelligence.",[79,3268,3270],{"id":3269},"web-widget","Web Widget",[19,3272,3273],{},"A lightweight JavaScript widget that embeds in any website. It loads asynchronously (under 30KB initial payload), supports custom theming to match your brand, and works across all modern browsers. The widget communicates with the Connekz backend via WebSocket for real-time conversation.",[79,3275,3277],{"id":3276},"inline-chat","Inline Chat",[19,3279,3280,3281,3284],{},"For businesses that want the AI agent integrated directly into their ",[230,3282,3283],{"href":2353},"website pages"," rather than as a floating widget. The inline mode renders within a designated container element and can be styled to look like a native part of the page.",[14,3286,3288],{"id":3287},"what-we-learned-building-production-ai-agents","What We Learned Building Production AI Agents",[19,3290,3291],{},"Shipping AI agents into production customer-facing environments taught us lessons that no research paper or demo could.",[79,3293,3295],{"id":3294},"hallucination-mitigation-is-an-engineering-problem","Hallucination Mitigation Is an Engineering Problem",[19,3297,3298],{},"LLMs hallucinate. This is a fundamental characteristic, not a bug to be patched. Our mitigation strategy is multi-layered:",[1711,3300,3301,3307,3313,3319],{},[50,3302,3303,3306],{},[23,3304,3305],{},"Constrain the knowledge domain",": The agent only answers questions about topics covered in the RAG knowledge base. For everything else, it responds honestly: \"I don't have information about that. Let me connect you with a team member who can help.\"",[50,3308,3309,3312],{},[23,3310,3311],{},"Fact-check against structured data",": When the agent states a price, availability, or policy, the system cross-references against structured data sources (not just the RAG corpus) before presenting the information.",[50,3314,3315,3318],{},[23,3316,3317],{},"Confidence scoring",": Every response includes an internal confidence score. Below a configurable threshold, the agent flags uncertainty to the customer or escalates to a human.",[50,3320,3321,3324],{},[23,3322,3323],{},"Post-response validation",": A lightweight validation model reviews each response before it is sent, checking for contradictions with known facts and flagging potential hallucinations.",[79,3326,3328],{"id":3327},"graceful-handoff-to-humans-is-not-optional","Graceful Handoff to Humans Is Not Optional",[19,3330,3331],{},"No AI agent can handle every situation. The quality of your handoff process determines whether a complex interaction becomes a satisfied customer or a lost one.",[19,3333,3334],{},"Connekz implements three types of handoff:",[47,3336,3337,3343,3349],{},[50,3338,3339,3342],{},[23,3340,3341],{},"Proactive handoff",": The agent detects it cannot resolve the issue (low confidence, out-of-scope request, detected frustration) and initiates transfer.",[50,3344,3345,3348],{},[23,3346,3347],{},"Customer-requested handoff",": The customer explicitly asks to speak with a person. This is honoured immediately, no friction, no attempts to retain the conversation.",[50,3350,3351,3354],{},[23,3352,3353],{},"Escalation handoff",": A human supervisor monitoring the conversation intervenes and takes over.",[19,3356,3357],{},"In all cases, the full conversation history and context are passed to the human agent. The customer never has to repeat themselves.",[79,3359,3361],{"id":3360},"latency-matters-more-than-you-think","Latency Matters More Than You Think",[19,3363,3364],{},"In conversational AI, perceived intelligence is heavily influenced by response speed. A technically superior response delivered in 5 seconds feels worse than a good response delivered in 800ms. Users begin to disengage after 2 seconds of silence.",[19,3366,3367],{},"We optimise for latency at every layer:",[1711,3369,3370,3373,3376,3379],{},[50,3371,3372],{},"Intent classification completes in under 50ms",[50,3374,3375],{},"RAG retrieval runs in parallel with conversation context assembly",[50,3377,3378],{},"Response streaming begins before the full response is generated",[50,3380,3381],{},"Tool calls execute asynchronously where possible",[19,3383,3384],{},"Our p95 response latency for text interactions is under 1.2 seconds. For voice, we target under 1.5 seconds from end-of-speech detection to start-of-response playback.",[79,3386,3388],{"id":3387},"monitoring-and-continuous-improvement","Monitoring and Continuous Improvement",[19,3390,3391],{},"Deploying an AI agent is not a launch-and-forget operation. We monitor every conversation across multiple dimensions:",[1711,3393,3394,3400,3406,3412,3418],{},[50,3395,3396,3399],{},[23,3397,3398],{},"Resolution rate",": What percentage of conversations reach a successful outcome without human handoff?",[50,3401,3402,3405],{},[23,3403,3404],{},"Accuracy rate",": Human evaluators review volenteraly provided sampled conversations for factual accuracy and appropriateness.",[50,3407,3408,3411],{},[23,3409,3410],{},"Customer satisfaction",": Post-conversation ratings and sentiment analysis.",[50,3413,3414,3417],{},[23,3415,3416],{},"Tool call success rate",": What percentage of bookings, updates, and actions complete successfully?",[50,3419,3420,3423],{},[23,3421,3422],{},"Escalation patterns",": Which topics or scenarios consistently require human handoff? These inform knowledge base improvements and model updates.",[19,3425,3426],{},"We feed these metrics back into a continuous improvement loop. Every week, the lowest-performing conversation patterns are reviewed, and the knowledge base, prompts, and guardrails are updated accordingly.",[14,3428,3430],{"id":3429},"results-our-clients-see","Results Our Clients See",[19,3432,3433],{},"The impact of deploying Connekz varies by industry and use case, but the patterns are consistent.",[124,3435,3436,3449],{},[127,3437,3438],{},[130,3439,3440,3443,3446],{},[133,3441,3442],{},"Metric",[133,3444,3445],{},"Typical Before",[133,3447,3448],{},"Typical After",[143,3450,3451,3462,3473,3484,3495,3506],{},[130,3452,3453,3456,3459],{},[148,3454,3455],{},"After-hours response rate",[148,3457,3458],{},"0% (voicemail/email only)",[148,3460,3461],{},"95%+ instant response",[130,3463,3464,3467,3470],{},[148,3465,3466],{},"Average first response time",[148,3468,3469],{},"4-8 hours",[148,3471,3472],{},"Under 2 seconds",[130,3474,3475,3478,3481],{},[148,3476,3477],{},"Routine enquiry handling",[148,3479,3480],{},"100% human",[148,3482,3483],{},"70-80% automated",[130,3485,3486,3489,3492],{},[148,3487,3488],{},"Booking conversion (after-hours)",[148,3490,3491],{},"Near zero",[148,3493,3494],{},"35-50% of enquiries",[130,3496,3497,3500,3503],{},[148,3498,3499],{},"Support cost per interaction",[148,3501,3502],{},"$8-15",[148,3504,3505],{},"$0.50-2.00",[130,3507,3508,3511,3514],{},[148,3509,3510],{},"Customer satisfaction score",[148,3512,3513],{},"3.8/5.0",[148,3515,3516],{},"4.3/5.0",[19,3518,3519,3520,3523],{},"These numbers represent real outcomes from ",[230,3521,3522],{"href":251},"Connekz deployments"," across healthcare, professional services, and hospitality businesses.",[1162,3525,3526],{"type":322},[19,3527,3528,3529,3532],{},"The most surprising result: customer satisfaction scores typically ",[2180,3530,3531],{},"increase"," after AI agent deployment. Customers prefer an instant, accurate response from an AI over a delayed or inconsistent response from an overwhelmed human team.",[14,3534,3536],{"id":3535},"the-road-ahead","The Road Ahead",[19,3538,3539],{},"Connekz is not a finished product. It is a platform that evolves with advances in AI capabilities and our clients' needs. Our current development priorities include:",[1711,3541,3542,3548,3554,3564],{},[50,3543,3544,3547],{},[23,3545,3546],{},"Multi-agent orchestration",": Complex business processes that require coordination between specialised agents (a booking agent, a billing agent, a technical support agent) working together on a single customer interaction.",[50,3549,3550,3553],{},[23,3551,3552],{},"Proactive outreach",": Connekz initiating conversations based on triggers — appointment reminders, follow-up after service, re-engagement of lapsed customers.",[50,3555,3556,3563],{},[23,3557,3558,3559],{},"Deeper ",[230,3560,3562],{"href":3561},"/solutions/ai-solutions","AI integration",": Connecting Connekz to internal business intelligence, allowing the agent to make data-informed recommendations (e.g., suggesting the most popular service for a new customer based on similar customer patterns).",[50,3565,3566,3569],{},[23,3567,3568],{},"Industry-specific models",": Fine-tuned models for healthcare, legal, and financial services that understand domain-specific terminology, compliance requirements, and interaction patterns.",[19,3571,3572],{},"The gap between what customers expect and what most businesses can deliver is growing. AI agents are not a futuristic concept — they are a practical, deployable solution to a problem that every business faces today.",[2357,3574],{},[19,3576,3577],{},[2180,3578,3579,3580,3583],{},"Ready to deploy Connekz for your business? ",[230,3581,3582],{"href":2366},"Start a conversation with our team"," and see what intelligent automation can do for your customer experience.",[2370,3585,3586],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":289,"searchDepth":304,"depth":304,"links":3588},[3589,3590,3597,3601,3605,3611,3612],{"id":2432,"depth":304,"text":2433},{"id":2450,"depth":304,"text":2451,"children":3591},[3592,3593,3594,3595,3596],{"id":2457,"depth":319,"text":2458},{"id":2464,"depth":319,"text":2465},{"id":2471,"depth":319,"text":2472},{"id":2481,"depth":319,"text":2482},{"id":2844,"depth":319,"text":2845},{"id":2854,"depth":304,"text":2855,"children":3598},[3599,3600],{"id":2861,"depth":319,"text":2862},{"id":3179,"depth":319,"text":3180},{"id":3262,"depth":304,"text":3263,"children":3602},[3603,3604],{"id":3269,"depth":319,"text":3270},{"id":3276,"depth":319,"text":3277},{"id":3287,"depth":304,"text":3288,"children":3606},[3607,3608,3609,3610],{"id":3294,"depth":319,"text":3295},{"id":3327,"depth":319,"text":3328},{"id":3360,"depth":319,"text":3361},{"id":3387,"depth":319,"text":3388},{"id":3429,"depth":304,"text":3430},{"id":3535,"depth":304,"text":3536},"AI","2026-02-07","A behind-the-scenes look at building Connekz — the AI agent platform powering customer interactions for businesses across New Zealand and beyond.",{},"/blog/building-connekz-ai-agent","11 min read",{"title":2424,"description":3615},"blog/building-connekz-ai-agent",[252,3622,3623,3624],"AI Agents","Natural Language Processing","Product Engineering","3dweb7U44CHsXPjufugyInw62GeJ0CMrWfns7Q78EI8",{"id":3627,"title":3628,"author":3629,"body":3630,"category":5168,"coverImage":2407,"date":5169,"description":5170,"extension":2410,"featured":2411,"meta":5171,"navigation":365,"path":5172,"readingTime":5173,"seo":5174,"stem":5175,"tags":5176,"__hash__":5181},"blog/blog/signs-outgrown-infrastructure.md","5 Signs Your Business Has Outgrown Its Current Infrastructure",{"name":8,"role":9},{"type":11,"value":3631,"toc":5132},[3632,3636,3639,3642,3645,3650,3654,3657,3661,3678,3682,3685,3688,3786,3790,3793,3801,3806,3810,3813,3816,3833,3836,3839,3842,3845,3848,3851,3854,3857,4135,4140,4144,4147,4150,4167,4170,4173,4176,4179,4182,4208,4708,4714,4718,4721,4724,4741,4744,4747,4754,4757,4760,4763,4768,4788,4890,4895,4899,4902,4905,4922,4925,4928,4931,4934,4937,4969,5047,5051,5054,5057,5061,5064,5068,5071,5075,5078,5082,5085,5089,5092,5097,5101,5104,5107,5110,5112,5129],[14,3633,3635],{"id":3634},"when-your-infrastructure-becomes-the-bottleneck","When Your Infrastructure Becomes the Bottleneck",[19,3637,3638],{},"Infrastructure problems rarely announce themselves with a dramatic failure. They creep in gradually -- a deployment that takes a little longer than it used to, a cloud bill that climbs a few percent each month, an outage on a Friday evening that requires three engineers to diagnose. Each issue seems manageable in isolation, but together they form a pattern that signals something fundamental: your business has outgrown the infrastructure it runs on.",[19,3640,3641],{},"This is a problem we see repeatedly at CNEX when working with growing businesses. The infrastructure that served them well at 10 employees and 1,000 users starts to crack at 50 employees and 50,000 users. The tools and patterns that made sense three years ago become the very things holding the business back today.",[19,3643,3644],{},"The good news is that these problems follow predictable patterns. If you recognise the signs early, you can modernise proactively rather than being forced into an emergency migration during a crisis. Here are the five most reliable indicators that it is time to rethink your infrastructure.",[31,3646,3647],{},[19,3648,3649],{},"Infrastructure debt compounds faster than technical debt. By the time it becomes visible to the business, the cost of fixing it has already multiplied.",[14,3651,3653],{"id":3652},"sign-1-deployments-take-hours-or-days-instead-of-minutes","Sign 1: Deployments Take Hours (or Days) Instead of Minutes",[19,3655,3656],{},"If getting a code change into production feels like a project in itself, your deployment pipeline is telling you something important. Healthy deployment processes take minutes, not hours. When deployments become slow, infrequent, and stressful, it creates a cascading effect across the entire engineering organisation.",[79,3658,3660],{"id":3659},"what-this-looks-like","What This Looks Like",[1711,3662,3663,3666,3669,3672,3675],{},[50,3664,3665],{},"Engineers batch changes into large, risky releases because deploying is painful",[50,3667,3668],{},"Someone has to manually SSH into servers to pull code, restart services, or run database migrations",[50,3670,3671],{},"There is a \"deployment day\" -- a designated window where releases happen, often accompanied by anxiety",[50,3673,3674],{},"Rollbacks are manual, time-consuming, and sometimes impossible",[50,3676,3677],{},"Nobody deploys on Fridays (or Thursdays, or really any day they can avoid)",[79,3679,3681],{"id":3680},"why-it-happens","Why It Happens",[19,3683,3684],{},"Most deployment pain comes from a lack of automation. The application was initially deployed by hand, and as the system grew, the manual process was never replaced with a proper CI/CD pipeline. Each new service, database, or dependency added another manual step to the process.",[19,3686,3687],{},"Sometimes the problem is architectural. Monolithic applications that require the entire system to be deployed as a single unit make it impossible to ship small, incremental changes safely.",[284,3689,3691],{"className":1098,"code":3690,"language":1100,"meta":289,"style":289},"# What a modern deployment should look like\n# Push to main triggers automated pipeline:\n# 1. Run tests (2-3 min)\n# 2. Build container image (1-2 min)\n# 3. Deploy to staging, run smoke tests (2-3 min)\n# 4. Progressive rollout to production (5-10 min)\n# Total: under 15 minutes, zero manual steps\n\n# Example: GitHub Actions pipeline trigger\ngit push origin main\n# Pipeline runs automatically:\n# - Linting and type checking\n# - Unit and integration tests\n# - Container build and push to registry\n# - Kubernetes rolling deployment\n# - Automated smoke tests against production\n# - Slack notification on success or failure\n",[291,3692,3693,3698,3703,3708,3713,3718,3723,3728,3732,3737,3751,3756,3761,3766,3771,3776,3781],{"__ignoreMap":289},[294,3694,3695],{"class":296,"line":297},[294,3696,3697],{"class":300},"# What a modern deployment should look like\n",[294,3699,3700],{"class":296,"line":304},[294,3701,3702],{"class":300},"# Push to main triggers automated pipeline:\n",[294,3704,3705],{"class":296,"line":319},[294,3706,3707],{"class":300},"# 1. Run tests (2-3 min)\n",[294,3709,3710],{"class":296,"line":328},[294,3711,3712],{"class":300},"# 2. Build container image (1-2 min)\n",[294,3714,3715],{"class":296,"line":340},[294,3716,3717],{"class":300},"# 3. Deploy to staging, run smoke tests (2-3 min)\n",[294,3719,3720],{"class":296,"line":351},[294,3721,3722],{"class":300},"# 4. Progressive rollout to production (5-10 min)\n",[294,3724,3725],{"class":296,"line":362},[294,3726,3727],{"class":300},"# Total: under 15 minutes, zero manual steps\n",[294,3729,3730],{"class":296,"line":369},[294,3731,366],{"emptyLinePlaceholder":365},[294,3733,3734],{"class":296,"line":377},[294,3735,3736],{"class":300},"# Example: GitHub Actions pipeline trigger\n",[294,3738,3739,3742,3745,3748],{"class":296,"line":385},[294,3740,3741],{"class":1112},"git",[294,3743,3744],{"class":336}," push",[294,3746,3747],{"class":336}," origin",[294,3749,3750],{"class":336}," main\n",[294,3752,3753],{"class":296,"line":393},[294,3754,3755],{"class":300},"# Pipeline runs automatically:\n",[294,3757,3758],{"class":296,"line":404},[294,3759,3760],{"class":300},"# - Linting and type checking\n",[294,3762,3763],{"class":296,"line":415},[294,3764,3765],{"class":300},"# - Unit and integration tests\n",[294,3767,3768],{"class":296,"line":423},[294,3769,3770],{"class":300},"# - Container build and push to registry\n",[294,3772,3773],{"class":296,"line":432},[294,3774,3775],{"class":300},"# - Kubernetes rolling deployment\n",[294,3777,3778],{"class":296,"line":440},[294,3779,3780],{"class":300},"# - Automated smoke tests against production\n",[294,3782,3783],{"class":296,"line":451},[294,3784,3785],{"class":300},"# - Slack notification on success or failure\n",[79,3787,3789],{"id":3788},"what-to-do-about-it","What to Do About It",[19,3791,3792],{},"Invest in a proper CI/CD pipeline. At minimum, you need automated testing on every commit, automated builds, and a one-command (or zero-command) deployment process. Tools like GitHub Actions, GitLab CI, or cloud-native solutions like AWS CodePipeline make this achievable in days, not months.",[19,3794,3795,3796,3800],{},"Our ",[230,3797,3799],{"href":3798},"/solutions/platform-engineering","platform engineering team"," typically starts infrastructure engagements by fixing the deployment pipeline first, because everything else depends on the ability to ship changes quickly and safely.",[1162,3802,3803],{"type":1164},[19,3804,3805],{},"A good benchmark: your team should be able to deploy a one-line code change to production in under 15 minutes, with zero manual steps, at any time of day. If you are not there, your deployment pipeline needs attention.",[14,3807,3809],{"id":3808},"sign-2-your-cloud-bill-is-climbing-but-performance-is-not","Sign 2: Your Cloud Bill Is Climbing but Performance Is Not",[19,3811,3812],{},"A rising cloud bill is not inherently a problem -- if your business is growing and your infrastructure is scaling to match demand, costs will increase. The red flag is when costs climb without a corresponding improvement in performance, capacity, or user experience.",[79,3814,3660],{"id":3815},"what-this-looks-like-1",[1711,3817,3818,3821,3824,3827,3830],{},[50,3819,3820],{},"Monthly cloud spend has increased 30-50% year over year, but traffic has only grown 10-15%",[50,3822,3823],{},"You are running oversized instances \"just in case\" because right-sizing feels risky",[50,3825,3826],{},"Dev and staging environments run 24/7 at production scale",[50,3828,3829],{},"Nobody on the team can explain what each line item on the cloud bill represents",[50,3831,3832],{},"There is no tagging strategy, so costs cannot be attributed to specific services or teams",[79,3834,3681],{"id":3835},"why-it-happens-1",[19,3837,3838],{},"Cloud cost creep usually results from a combination of over-provisioning and neglect. Early in a project, engineers choose instance sizes with generous headroom because they do not yet understand the application's resource profile. Those instances never get right-sized because nobody is monitoring utilisation.",[19,3840,3841],{},"Over time, resources accumulate. Old test environments are never decommissioned. Snapshots and backups pile up. Load balancers, IP addresses, and storage volumes from experiments persist long after the experiments end.",[19,3843,3844],{},"The absence of auto-scaling is another major contributor. Without auto-scaling, you provision for peak load and pay for that capacity 24/7, even when actual usage is a fraction of the peak.",[79,3846,3789],{"id":3847},"what-to-do-about-it-1",[19,3849,3850],{},"Start with visibility. Implement resource tagging so you can attribute costs to services, teams, and environments. Use your cloud provider's cost explorer to identify the top 10 spending categories and investigate each one.",[19,3852,3853],{},"Next, implement auto-scaling for compute resources. A well-configured auto-scaling group can reduce compute costs by 40-60% by scaling down during low-traffic periods.",[19,3855,3856],{},"Finally, audit non-production environments. Dev and staging environments should scale down or shut off outside of business hours. This single change often saves 20-30% of total cloud spend.",[284,3858,3860],{"className":1181,"code":3859,"language":1183,"meta":289,"style":289},"// Example: Kubernetes Horizontal Pod Autoscaler configuration\n// Automatically scales pods based on CPU and memory utilisation\nconst hpaConfig = {\n  apiVersion: 'autoscaling/v2',\n  kind: 'HorizontalPodAutoscaler',\n  metadata: { name: 'api-service', namespace: 'production' },\n  spec: {\n    scaleTargetRef: {\n      apiVersion: 'apps/v1',\n      kind: 'Deployment',\n      name: 'api-service',\n    },\n    minReplicas: 2,\n    maxReplicas: 20,\n    metrics: [\n      {\n        type: 'Resource',\n        resource: { name: 'cpu', target: { type: 'Utilization', averageUtilization: 65 } },\n      },\n      {\n        type: 'Resource',\n        resource: { name: 'memory', target: { type: 'Utilization', averageUtilization: 75 } },\n      },\n    ],\n    behavior: {\n      scaleUp: { stabilizationWindowSeconds: 60, policies: [{ type: 'Percent', value: 50, periodSeconds: 60 }] },\n      scaleDown: { stabilizationWindowSeconds: 300, policies: [{ type: 'Percent', value: 25, periodSeconds: 120 }] },\n    },\n  },\n};\n",[291,3861,3862,3867,3872,3883,3893,3903,3919,3924,3929,3939,3949,3958,3962,3972,3982,3987,3992,4001,4024,4028,4032,4040,4058,4062,4067,4072,4099,4123,4127,4131],{"__ignoreMap":289},[294,3863,3864],{"class":296,"line":297},[294,3865,3866],{"class":300},"// Example: Kubernetes Horizontal Pod Autoscaler configuration\n",[294,3868,3869],{"class":296,"line":304},[294,3870,3871],{"class":300},"// Automatically scales pods based on CPU and memory utilisation\n",[294,3873,3874,3876,3879,3881],{"class":296,"line":319},[294,3875,1217],{"class":1195},[294,3877,3878],{"class":315}," hpaConfig",[294,3880,1223],{"class":1195},[294,3882,1282],{"class":311},[294,3884,3885,3888,3891],{"class":296,"line":328},[294,3886,3887],{"class":311},"  apiVersion: ",[294,3889,3890],{"class":336},"'autoscaling/v2'",[294,3892,1243],{"class":311},[294,3894,3895,3898,3901],{"class":296,"line":340},[294,3896,3897],{"class":311},"  kind: ",[294,3899,3900],{"class":336},"'HorizontalPodAutoscaler'",[294,3902,1243],{"class":311},[294,3904,3905,3908,3911,3914,3917],{"class":296,"line":351},[294,3906,3907],{"class":311},"  metadata: { name: ",[294,3909,3910],{"class":336},"'api-service'",[294,3912,3913],{"class":311},", namespace: ",[294,3915,3916],{"class":336},"'production'",[294,3918,2744],{"class":311},[294,3920,3921],{"class":296,"line":362},[294,3922,3923],{"class":311},"  spec: {\n",[294,3925,3926],{"class":296,"line":369},[294,3927,3928],{"class":311},"    scaleTargetRef: {\n",[294,3930,3931,3934,3937],{"class":296,"line":377},[294,3932,3933],{"class":311},"      apiVersion: ",[294,3935,3936],{"class":336},"'apps/v1'",[294,3938,1243],{"class":311},[294,3940,3941,3944,3947],{"class":296,"line":385},[294,3942,3943],{"class":311},"      kind: ",[294,3945,3946],{"class":336},"'Deployment'",[294,3948,1243],{"class":311},[294,3950,3951,3954,3956],{"class":296,"line":393},[294,3952,3953],{"class":311},"      name: ",[294,3955,3910],{"class":336},[294,3957,1243],{"class":311},[294,3959,3960],{"class":296,"line":404},[294,3961,3147],{"class":311},[294,3963,3964,3967,3970],{"class":296,"line":415},[294,3965,3966],{"class":311},"    minReplicas: ",[294,3968,3969],{"class":315},"2",[294,3971,1243],{"class":311},[294,3973,3974,3977,3980],{"class":296,"line":423},[294,3975,3976],{"class":311},"    maxReplicas: ",[294,3978,3979],{"class":315},"20",[294,3981,1243],{"class":311},[294,3983,3984],{"class":296,"line":432},[294,3985,3986],{"class":311},"    metrics: [\n",[294,3988,3989],{"class":296,"line":440},[294,3990,3991],{"class":311},"      {\n",[294,3993,3994,3996,3999],{"class":296,"line":451},[294,3995,2938],{"class":311},[294,3997,3998],{"class":336},"'Resource'",[294,4000,1243],{"class":311},[294,4002,4003,4006,4009,4012,4015,4018,4021],{"class":296,"line":459},[294,4004,4005],{"class":311},"        resource: { name: ",[294,4007,4008],{"class":336},"'cpu'",[294,4010,4011],{"class":311},", target: { type: ",[294,4013,4014],{"class":336},"'Utilization'",[294,4016,4017],{"class":311},", averageUtilization: ",[294,4019,4020],{"class":315},"65",[294,4022,4023],{"class":311}," } },\n",[294,4025,4026],{"class":296,"line":467},[294,4027,2983],{"class":311},[294,4029,4030],{"class":296,"line":475},[294,4031,3991],{"class":311},[294,4033,4034,4036,4038],{"class":296,"line":486},[294,4035,2938],{"class":311},[294,4037,3998],{"class":336},[294,4039,1243],{"class":311},[294,4041,4042,4044,4047,4049,4051,4053,4056],{"class":296,"line":494},[294,4043,4005],{"class":311},[294,4045,4046],{"class":336},"'memory'",[294,4048,4011],{"class":311},[294,4050,4014],{"class":336},[294,4052,4017],{"class":311},[294,4054,4055],{"class":315},"75",[294,4057,4023],{"class":311},[294,4059,4060],{"class":296,"line":502},[294,4061,2983],{"class":311},[294,4063,4064],{"class":296,"line":513},[294,4065,4066],{"class":311},"    ],\n",[294,4068,4069],{"class":296,"line":521},[294,4070,4071],{"class":311},"    behavior: {\n",[294,4073,4074,4077,4079,4082,4085,4088,4091,4094,4096],{"class":296,"line":529},[294,4075,4076],{"class":311},"      scaleUp: { stabilizationWindowSeconds: ",[294,4078,1781],{"class":315},[294,4080,4081],{"class":311},", policies: [{ type: ",[294,4083,4084],{"class":336},"'Percent'",[294,4086,4087],{"class":311},", value: ",[294,4089,4090],{"class":315},"50",[294,4092,4093],{"class":311},", periodSeconds: ",[294,4095,1781],{"class":315},[294,4097,4098],{"class":311}," }] },\n",[294,4100,4101,4104,4107,4109,4111,4113,4116,4118,4121],{"class":296,"line":537},[294,4102,4103],{"class":311},"      scaleDown: { stabilizationWindowSeconds: ",[294,4105,4106],{"class":315},"300",[294,4108,4081],{"class":311},[294,4110,4084],{"class":336},[294,4112,4087],{"class":311},[294,4114,4115],{"class":315},"25",[294,4117,4093],{"class":311},[294,4119,4120],{"class":315},"120",[294,4122,4098],{"class":311},[294,4124,4125],{"class":296,"line":548},[294,4126,3147],{"class":311},[294,4128,4129],{"class":296,"line":556},[294,4130,1922],{"class":311},[294,4132,4133],{"class":296,"line":566},[294,4134,3176],{"class":311},[1162,4136,4137],{"type":322},[19,4138,4139],{},"A common rule of thumb: if your average CPU utilisation across compute resources is below 30%, you are significantly over-provisioned. Healthy utilisation targets are 50-70% for production workloads.",[14,4141,4143],{"id":4142},"sign-3-a-single-failure-cascades-across-the-entire-system","Sign 3: A Single Failure Cascades Across the Entire System",[19,4145,4146],{},"When one component fails and it takes everything else down with it, you have a resilience problem. In a well-architected system, failures are isolated. A payment processing issue should not take down the product catalogue. A search index rebuild should not make the checkout flow unavailable.",[79,4148,3660],{"id":4149},"what-this-looks-like-2",[1711,4151,4152,4155,4158,4161,4164],{},[50,4153,4154],{},"A single database going slow causes the entire application to become unresponsive",[50,4156,4157],{},"One misbehaving API endpoint consumes all available connections, starving other endpoints",[50,4159,4160],{},"A third-party service outage (payment gateway, email provider) halts your entire application",[50,4162,4163],{},"Deploying one service requires coordinated deployments of three other services",[50,4165,4166],{},"There is a single database that every service reads from and writes to",[79,4168,3681],{"id":4169},"why-it-happens-2",[19,4171,4172],{},"Cascading failures are the hallmark of a monolithic architecture that has not been designed for fault isolation. When all components share the same process, the same database, and the same connection pools, a problem in any one area affects all others.",[19,4174,4175],{},"Even in distributed systems, cascading failures occur when services are tightly coupled -- when service A calls service B synchronously, and service B calls service C, and any timeout or failure propagates up the entire chain.",[79,4177,3789],{"id":4178},"what-to-do-about-it-2",[19,4180,4181],{},"The long-term solution is to decompose tightly coupled components and introduce fault isolation patterns. But you do not need to undertake a full microservices migration to improve resilience. Start with these high-impact changes:",[1711,4183,4184,4190,4196,4202],{},[50,4185,4186,4189],{},[23,4187,4188],{},"Circuit breakers",": Detect when a downstream service is failing and stop sending requests, returning a fallback response instead",[50,4191,4192,4195],{},[23,4193,4194],{},"Bulkhead pattern",": Isolate connection pools and thread pools per service so one slow dependency cannot exhaust shared resources",[50,4197,4198,4201],{},[23,4199,4200],{},"Asynchronous communication",": Replace synchronous API calls with message queues for non-time-critical operations",[50,4203,4204,4207],{},[23,4205,4206],{},"Database read replicas",": Separate read and write traffic to prevent analytics queries from impacting transactional workloads",[284,4209,4211],{"className":1181,"code":4210,"language":1183,"meta":289,"style":289},"// Circuit breaker pattern example\nclass CircuitBreaker {\n  private failures = 0;\n  private lastFailureTime = 0;\n  private state: 'closed' | 'open' | 'half-open' = 'closed';\n\n  constructor(\n    private threshold: number = 5,\n    private resetTimeout: number = 30000,\n  ) {}\n\n  async execute\u003CT>(fn: () => Promise\u003CT>, fallback: () => T): Promise\u003CT> {\n    if (this.state === 'open') {\n      if (Date.now() - this.lastFailureTime > this.resetTimeout) {\n        this.state = 'half-open';\n      } else {\n        return fallback(); // Return fallback instead of cascading the failure\n      }\n    }\n\n    try {\n      const result = await fn();\n      this.onSuccess();\n      return result;\n    } catch (error) {\n      this.onFailure();\n      return fallback();\n    }\n  }\n\n  private onSuccess() {\n    this.failures = 0;\n    this.state = 'closed';\n  }\n\n  private onFailure() {\n    this.failures++;\n    this.lastFailureTime = Date.now();\n    if (this.failures >= this.threshold) {\n      this.state = 'open';\n    }\n  }\n}\n",[291,4212,4213,4218,4228,4243,4256,4284,4288,4295,4313,4331,4336,4340,4396,4417,4447,4461,4471,4485,4490,4494,4498,4505,4523,4536,4544,4555,4566,4574,4578,4582,4586,4596,4610,4622,4626,4630,4639,4651,4666,4684,4696,4700,4704],{"__ignoreMap":289},[294,4214,4215],{"class":296,"line":297},[294,4216,4217],{"class":300},"// Circuit breaker pattern example\n",[294,4219,4220,4223,4226],{"class":296,"line":304},[294,4221,4222],{"class":1195},"class",[294,4224,4225],{"class":1112}," CircuitBreaker",[294,4227,1282],{"class":311},[294,4229,4230,4233,4236,4238,4241],{"class":296,"line":319},[294,4231,4232],{"class":1195},"  private",[294,4234,4235],{"class":1376}," failures",[294,4237,1223],{"class":1195},[294,4239,4240],{"class":315}," 0",[294,4242,1208],{"class":311},[294,4244,4245,4247,4250,4252,4254],{"class":296,"line":328},[294,4246,4232],{"class":1195},[294,4248,4249],{"class":1376}," lastFailureTime",[294,4251,1223],{"class":1195},[294,4253,4240],{"class":315},[294,4255,1208],{"class":311},[294,4257,4258,4260,4263,4265,4268,4270,4273,4275,4278,4280,4282],{"class":296,"line":340},[294,4259,4232],{"class":1195},[294,4261,4262],{"class":1376}," state",[294,4264,2092],{"class":1195},[294,4266,4267],{"class":336}," 'closed'",[294,4269,2120],{"class":1195},[294,4271,4272],{"class":336}," 'open'",[294,4274,2120],{"class":1195},[294,4276,4277],{"class":336}," 'half-open'",[294,4279,1223],{"class":1195},[294,4281,4267],{"class":336},[294,4283,1208],{"class":311},[294,4285,4286],{"class":296,"line":351},[294,4287,366],{"emptyLinePlaceholder":365},[294,4289,4290,4293],{"class":296,"line":362},[294,4291,4292],{"class":1195},"  constructor",[294,4294,2610],{"class":311},[294,4296,4297,4300,4303,4305,4307,4309,4311],{"class":296,"line":369},[294,4298,4299],{"class":1195},"    private",[294,4301,4302],{"class":1376}," threshold",[294,4304,2092],{"class":1195},[294,4306,2147],{"class":315},[294,4308,1223],{"class":1195},[294,4310,2646],{"class":315},[294,4312,1243],{"class":311},[294,4314,4315,4317,4320,4322,4324,4326,4329],{"class":296,"line":377},[294,4316,4299],{"class":1195},[294,4318,4319],{"class":1376}," resetTimeout",[294,4321,2092],{"class":1195},[294,4323,2147],{"class":315},[294,4325,1223],{"class":1195},[294,4327,4328],{"class":315}," 30000",[294,4330,1243],{"class":311},[294,4332,4333],{"class":296,"line":385},[294,4334,4335],{"class":311},"  ) {}\n",[294,4337,4338],{"class":296,"line":393},[294,4339,366],{"emptyLinePlaceholder":365},[294,4341,4342,4345,4348,4350,4352,4355,4358,4360,4362,4364,4366,4368,4370,4373,4376,4378,4380,4382,4384,4386,4388,4390,4392,4394],{"class":296,"line":404},[294,4343,4344],{"class":1195},"  async",[294,4346,4347],{"class":1112}," execute",[294,4349,2078],{"class":311},[294,4351,2081],{"class":1112},[294,4353,4354],{"class":311},">(",[294,4356,4357],{"class":1112},"fn",[294,4359,2092],{"class":1195},[294,4361,1301],{"class":311},[294,4363,1279],{"class":1195},[294,4365,2658],{"class":1112},[294,4367,2078],{"class":311},[294,4369,2081],{"class":1112},[294,4371,4372],{"class":311},">, ",[294,4374,4375],{"class":1112},"fallback",[294,4377,2092],{"class":1195},[294,4379,1301],{"class":311},[294,4381,1279],{"class":1195},[294,4383,2095],{"class":1112},[294,4385,2653],{"class":311},[294,4387,2092],{"class":1195},[294,4389,2658],{"class":1112},[294,4391,2078],{"class":311},[294,4393,2081],{"class":1112},[294,4395,2084],{"class":311},[294,4397,4398,4401,4403,4406,4409,4412,4414],{"class":296,"line":415},[294,4399,4400],{"class":1195},"    if",[294,4402,1568],{"class":311},[294,4404,4405],{"class":315},"this",[294,4407,4408],{"class":311},".state ",[294,4410,4411],{"class":1195},"===",[294,4413,4272],{"class":336},[294,4415,4416],{"class":311},") {\n",[294,4418,4419,4422,4425,4428,4431,4434,4437,4440,4442,4444],{"class":296,"line":423},[294,4420,4421],{"class":1195},"      if",[294,4423,4424],{"class":311}," (Date.",[294,4426,4427],{"class":1112},"now",[294,4429,4430],{"class":311},"() ",[294,4432,4433],{"class":1195},"-",[294,4435,4436],{"class":315}," this",[294,4438,4439],{"class":311},".lastFailureTime ",[294,4441,2784],{"class":1195},[294,4443,4436],{"class":315},[294,4445,4446],{"class":311},".resetTimeout) {\n",[294,4448,4449,4452,4454,4457,4459],{"class":296,"line":432},[294,4450,4451],{"class":315},"        this",[294,4453,4408],{"class":311},[294,4455,4456],{"class":1195},"=",[294,4458,4277],{"class":336},[294,4460,1208],{"class":311},[294,4462,4463,4466,4469],{"class":296,"line":440},[294,4464,4465],{"class":311},"      } ",[294,4467,4468],{"class":1195},"else",[294,4470,1282],{"class":311},[294,4472,4473,4476,4479,4482],{"class":296,"line":451},[294,4474,4475],{"class":1195},"        return",[294,4477,4478],{"class":1112}," fallback",[294,4480,4481],{"class":311},"(); ",[294,4483,4484],{"class":300},"// Return fallback instead of cascading the failure\n",[294,4486,4487],{"class":296,"line":459},[294,4488,4489],{"class":311},"      }\n",[294,4491,4492],{"class":296,"line":467},[294,4493,2293],{"class":311},[294,4495,4496],{"class":296,"line":475},[294,4497,366],{"emptyLinePlaceholder":365},[294,4499,4500,4503],{"class":296,"line":486},[294,4501,4502],{"class":1195},"    try",[294,4504,1282],{"class":311},[294,4506,4507,4510,4513,4515,4517,4520],{"class":296,"line":494},[294,4508,4509],{"class":1195},"      const",[294,4511,4512],{"class":315}," result",[294,4514,1223],{"class":1195},[294,4516,1590],{"class":1195},[294,4518,4519],{"class":1112}," fn",[294,4521,4522],{"class":311},"();\n",[294,4524,4525,4528,4531,4534],{"class":296,"line":502},[294,4526,4527],{"class":315},"      this",[294,4529,4530],{"class":311},".",[294,4532,4533],{"class":1112},"onSuccess",[294,4535,4522],{"class":311},[294,4537,4538,4541],{"class":296,"line":513},[294,4539,4540],{"class":1195},"      return",[294,4542,4543],{"class":311}," result;\n",[294,4545,4546,4549,4552],{"class":296,"line":521},[294,4547,4548],{"class":311},"    } ",[294,4550,4551],{"class":1195},"catch",[294,4553,4554],{"class":311}," (error) {\n",[294,4556,4557,4559,4561,4564],{"class":296,"line":529},[294,4558,4527],{"class":315},[294,4560,4530],{"class":311},[294,4562,4563],{"class":1112},"onFailure",[294,4565,4522],{"class":311},[294,4567,4568,4570,4572],{"class":296,"line":537},[294,4569,4540],{"class":1195},[294,4571,4478],{"class":1112},[294,4573,4522],{"class":311},[294,4575,4576],{"class":296,"line":548},[294,4577,2293],{"class":311},[294,4579,4580],{"class":296,"line":556},[294,4581,2298],{"class":311},[294,4583,4584],{"class":296,"line":566},[294,4585,366],{"emptyLinePlaceholder":365},[294,4587,4588,4590,4593],{"class":296,"line":573},[294,4589,4232],{"class":1195},[294,4591,4592],{"class":1112}," onSuccess",[294,4594,4595],{"class":311},"() {\n",[294,4597,4598,4601,4604,4606,4608],{"class":296,"line":580},[294,4599,4600],{"class":315},"    this",[294,4602,4603],{"class":311},".failures ",[294,4605,4456],{"class":1195},[294,4607,4240],{"class":315},[294,4609,1208],{"class":311},[294,4611,4612,4614,4616,4618,4620],{"class":296,"line":587},[294,4613,4600],{"class":315},[294,4615,4408],{"class":311},[294,4617,4456],{"class":1195},[294,4619,4267],{"class":336},[294,4621,1208],{"class":311},[294,4623,4624],{"class":296,"line":597},[294,4625,2298],{"class":311},[294,4627,4628],{"class":296,"line":605},[294,4629,366],{"emptyLinePlaceholder":365},[294,4631,4632,4634,4637],{"class":296,"line":615},[294,4633,4232],{"class":1195},[294,4635,4636],{"class":1112}," onFailure",[294,4638,4595],{"class":311},[294,4640,4641,4643,4646,4649],{"class":296,"line":622},[294,4642,4600],{"class":315},[294,4644,4645],{"class":311},".failures",[294,4647,4648],{"class":1195},"++",[294,4650,1208],{"class":311},[294,4652,4653,4655,4657,4659,4662,4664],{"class":296,"line":629},[294,4654,4600],{"class":315},[294,4656,4439],{"class":311},[294,4658,4456],{"class":1195},[294,4660,4661],{"class":311}," Date.",[294,4663,4427],{"class":1112},[294,4665,4522],{"class":311},[294,4667,4668,4670,4672,4674,4676,4679,4681],{"class":296,"line":636},[294,4669,4400],{"class":1195},[294,4671,1568],{"class":311},[294,4673,4405],{"class":315},[294,4675,4603],{"class":311},[294,4677,4678],{"class":1195},">=",[294,4680,4436],{"class":315},[294,4682,4683],{"class":311},".threshold) {\n",[294,4685,4686,4688,4690,4692,4694],{"class":296,"line":646},[294,4687,4527],{"class":315},[294,4689,4408],{"class":311},[294,4691,4456],{"class":1195},[294,4693,4272],{"class":336},[294,4695,1208],{"class":311},[294,4697,4698],{"class":296,"line":651},[294,4699,2293],{"class":311},[294,4701,4702],{"class":296,"line":659},[294,4703,2298],{"class":311},[294,4705,4706],{"class":296,"line":667},[294,4707,2159],{"class":311},[19,4709,3795,4710,4713],{},[230,4711,4712],{"href":2015},"cloud-native architecture practice"," frequently helps businesses introduce these patterns incrementally, starting with the most critical failure points and working outward.",[14,4715,4717],{"id":4716},"sign-4-your-team-spends-more-time-firefighting-than-building","Sign 4: Your Team Spends More Time Firefighting Than Building",[19,4719,4720],{},"When your engineers spend their days reacting to incidents rather than building new features, your infrastructure is consuming your most valuable resource: engineering time. This is not just an operational problem -- it is a strategic one, because every hour spent firefighting is an hour not spent on product development.",[79,4722,3660],{"id":4723},"what-this-looks-like-3",[1711,4725,4726,4729,4732,4735,4738],{},[50,4727,4728],{},"The on-call engineer is constantly pulled into incidents during working hours",[50,4730,4731],{},"There is no centralised logging or monitoring -- diagnosing issues requires SSHing into multiple servers",[50,4733,4734],{},"Alerts are either nonexistent (you learn about outages from customers) or so noisy that they are ignored",[50,4736,4737],{},"Post-mortems reveal the same root causes repeatedly",[50,4739,4740],{},"\"It works on my machine\" is a regular part of debugging conversations",[79,4742,3681],{"id":4743},"why-it-happens-3",[19,4745,4746],{},"Firefighting cultures emerge from a lack of observability. When you cannot see what your system is doing, you cannot prevent problems -- you can only react to them after they impact users.",[19,4748,4749,4750,4753],{},"The absence of structured logging, metrics collection, and distributed tracing means that diagnosing issues requires manual investigation. Engineers spend 30 minutes figuring out ",[2180,4751,4752],{},"where"," the problem is before they can spend 10 minutes fixing it.",[19,4755,4756],{},"Alert fatigue is the other side of the coin. When monitoring exists but is not properly tuned, the team is bombarded with low-priority notifications until they learn to ignore all of them -- including the critical ones.",[79,4758,3789],{"id":4759},"what-to-do-about-it-3",[19,4761,4762],{},"Build an observability stack that gives your team visibility into system behaviour before problems become incidents.",[19,4764,4765],{},[23,4766,4767],{},"The three pillars of observability:",[47,4769,4770,4776,4782],{},[50,4771,4772,4775],{},[23,4773,4774],{},"Logs",": Structured, centralised, and searchable. Every service should emit structured JSON logs with correlation IDs that trace a request across services",[50,4777,4778,4781],{},[23,4779,4780],{},"Metrics",": Time-series data covering system health (CPU, memory, disk, network) and application health (request rate, error rate, response latency)",[50,4783,4784,4787],{},[23,4785,4786],{},"Traces",": Distributed traces that show the full journey of a request through your system, including time spent in each service",[284,4789,4791],{"className":1098,"code":4790,"language":1100,"meta":289,"style":289},"# Example: setting up a basic observability stack with Grafana Cloud\n# 1. Deploy OpenTelemetry Collector as a sidecar or daemon\n# 2. Instrument your application with OpenTelemetry SDK\n# 3. Configure export to Grafana Cloud (Loki for logs, Mimir for metrics, Tempo for traces)\n\n# Quick health check: what percentage of your requests are failing?\n# If you cannot answer this question in under 30 seconds, you need better observability\ncurl -s \"https://your-grafana-instance/api/ds/query\" \\\n  -H \"Authorization: Bearer $GRAFANA_TOKEN\" \\\n  -d '{\n    \"queries\": [{\n      \"expr\": \"sum(rate(http_requests_total{status=~\\\"5..\\\"}[5m])) / sum(rate(http_requests_total[5m])) * 100\",\n      \"legendFormat\": \"Error Rate %\"\n    }]\n  }'\n",[291,4792,4793,4798,4803,4808,4813,4817,4822,4827,4841,4857,4865,4870,4875,4880,4885],{"__ignoreMap":289},[294,4794,4795],{"class":296,"line":297},[294,4796,4797],{"class":300},"# Example: setting up a basic observability stack with Grafana Cloud\n",[294,4799,4800],{"class":296,"line":304},[294,4801,4802],{"class":300},"# 1. Deploy OpenTelemetry Collector as a sidecar or daemon\n",[294,4804,4805],{"class":296,"line":319},[294,4806,4807],{"class":300},"# 2. Instrument your application with OpenTelemetry SDK\n",[294,4809,4810],{"class":296,"line":328},[294,4811,4812],{"class":300},"# 3. Configure export to Grafana Cloud (Loki for logs, Mimir for metrics, Tempo for traces)\n",[294,4814,4815],{"class":296,"line":340},[294,4816,366],{"emptyLinePlaceholder":365},[294,4818,4819],{"class":296,"line":351},[294,4820,4821],{"class":300},"# Quick health check: what percentage of your requests are failing?\n",[294,4823,4824],{"class":296,"line":362},[294,4825,4826],{"class":300},"# If you cannot answer this question in under 30 seconds, you need better observability\n",[294,4828,4829,4832,4835,4838],{"class":296,"line":369},[294,4830,4831],{"class":1112},"curl",[294,4833,4834],{"class":315}," -s",[294,4836,4837],{"class":336}," \"https://your-grafana-instance/api/ds/query\"",[294,4839,4840],{"class":315}," \\\n",[294,4842,4843,4846,4849,4852,4855],{"class":296,"line":377},[294,4844,4845],{"class":315},"  -H",[294,4847,4848],{"class":336}," \"Authorization: Bearer ",[294,4850,4851],{"class":311},"$GRAFANA_TOKEN",[294,4853,4854],{"class":336},"\"",[294,4856,4840],{"class":315},[294,4858,4859,4862],{"class":296,"line":385},[294,4860,4861],{"class":315},"  -d",[294,4863,4864],{"class":336}," '{\n",[294,4866,4867],{"class":296,"line":393},[294,4868,4869],{"class":336},"    \"queries\": [{\n",[294,4871,4872],{"class":296,"line":404},[294,4873,4874],{"class":336},"      \"expr\": \"sum(rate(http_requests_total{status=~\\\"5..\\\"}[5m])) / sum(rate(http_requests_total[5m])) * 100\",\n",[294,4876,4877],{"class":296,"line":415},[294,4878,4879],{"class":336},"      \"legendFormat\": \"Error Rate %\"\n",[294,4881,4882],{"class":296,"line":423},[294,4883,4884],{"class":336},"    }]\n",[294,4886,4887],{"class":296,"line":432},[294,4888,4889],{"class":336},"  }'\n",[1162,4891,4892],{"type":1164},[19,4893,4894],{},"Start with three dashboards: a system health overview, an application performance dashboard, and an error tracking view. These three dashboards will surface 80% of the issues your team currently discovers through manual investigation.",[14,4896,4898],{"id":4897},"sign-5-scaling-means-buy-a-bigger-server","Sign 5: Scaling Means \"Buy a Bigger Server\"",[19,4900,4901],{},"If your response to growing traffic is to upgrade to a larger instance type -- more CPU, more RAM, more disk -- you are vertically scaling, and you are approaching a ceiling. Vertical scaling has hard limits (there is a largest available instance type), becomes exponentially expensive, and provides zero redundancy.",[79,4903,3660],{"id":4904},"what-this-looks-like-4",[1711,4906,4907,4910,4913,4916,4919],{},[50,4908,4909],{},"Performance problems are solved by upgrading to a larger server instance",[50,4911,4912],{},"The application runs on a single server (or a small number of individually managed servers)",[50,4914,4915],{},"There is no load balancing -- all traffic hits one server",[50,4917,4918],{},"The database is a single instance with no replication",[50,4920,4921],{},"\"We need a bigger database\" comes up quarterly in planning meetings",[79,4923,3681],{"id":4924},"why-it-happens-4",[19,4926,4927],{},"Vertical scaling is the path of least resistance. It requires no architectural changes, no new tooling, and no new operational knowledge. You click a button in your cloud console, the server gets bigger, and the problem goes away -- temporarily.",[19,4929,4930],{},"This approach works until it does not. And when it stops working, the pivot to horizontal scaling is a significant engineering effort that is much harder to execute under pressure than it would have been to plan for proactively.",[79,4932,3789],{"id":4933},"what-to-do-about-it-4",[19,4935,4936],{},"The transition from vertical to horizontal scaling involves several infrastructure changes:",[1711,4938,4939,4945,4951,4957,4963],{},[50,4940,4941,4944],{},[23,4942,4943],{},"Containerise your application",": Package your application as a container image so it can run identically across any number of instances",[50,4946,4947,4950],{},[23,4948,4949],{},"Implement stateless design",": Ensure your application does not store session state on the server. Use external stores (Redis, database) for session data",[50,4952,4953,4956],{},[23,4954,4955],{},"Add a load balancer",": Distribute traffic across multiple instances. Cloud providers make this straightforward with managed load balancers",[50,4958,4959,4962],{},[23,4960,4961],{},"Set up auto-scaling",": Automatically add and remove instances based on traffic demand",[50,4964,4965,4968],{},[23,4966,4967],{},"Consider managed Kubernetes",": For applications with multiple services, Kubernetes provides a production-grade platform for orchestrating containers at scale",[284,4970,4972],{"className":1098,"code":4971,"language":1100,"meta":289,"style":289},"# Before: single server, vertical scaling\n# \"We need more CPU\" --> upgrade from t3.large to t3.2xlarge\n# Cost: $0.0832/hr --> $0.3328/hr (4x cost for 4x CPU)\n# Downtime required for resize: 5-15 minutes\n# Redundancy: none\n\n# After: horizontal scaling with containers\n# \"We need more capacity\" --> add more pods\n# kubectl scale deployment api-service --replicas=6\n# Cost: scales linearly with demand\n# Downtime: zero\n# Redundancy: built-in (multiple instances across availability zones)\n\n# Even better: auto-scaling handles it automatically\n# No manual intervention needed -- scales based on actual demand\n",[291,4973,4974,4979,4984,4989,4994,4999,5003,5008,5013,5018,5023,5028,5033,5037,5042],{"__ignoreMap":289},[294,4975,4976],{"class":296,"line":297},[294,4977,4978],{"class":300},"# Before: single server, vertical scaling\n",[294,4980,4981],{"class":296,"line":304},[294,4982,4983],{"class":300},"# \"We need more CPU\" --> upgrade from t3.large to t3.2xlarge\n",[294,4985,4986],{"class":296,"line":319},[294,4987,4988],{"class":300},"# Cost: $0.0832/hr --> $0.3328/hr (4x cost for 4x CPU)\n",[294,4990,4991],{"class":296,"line":328},[294,4992,4993],{"class":300},"# Downtime required for resize: 5-15 minutes\n",[294,4995,4996],{"class":296,"line":340},[294,4997,4998],{"class":300},"# Redundancy: none\n",[294,5000,5001],{"class":296,"line":351},[294,5002,366],{"emptyLinePlaceholder":365},[294,5004,5005],{"class":296,"line":362},[294,5006,5007],{"class":300},"# After: horizontal scaling with containers\n",[294,5009,5010],{"class":296,"line":369},[294,5011,5012],{"class":300},"# \"We need more capacity\" --> add more pods\n",[294,5014,5015],{"class":296,"line":377},[294,5016,5017],{"class":300},"# kubectl scale deployment api-service --replicas=6\n",[294,5019,5020],{"class":296,"line":385},[294,5021,5022],{"class":300},"# Cost: scales linearly with demand\n",[294,5024,5025],{"class":296,"line":393},[294,5026,5027],{"class":300},"# Downtime: zero\n",[294,5029,5030],{"class":296,"line":404},[294,5031,5032],{"class":300},"# Redundancy: built-in (multiple instances across availability zones)\n",[294,5034,5035],{"class":296,"line":415},[294,5036,366],{"emptyLinePlaceholder":365},[294,5038,5039],{"class":296,"line":423},[294,5040,5041],{"class":300},"# Even better: auto-scaling handles it automatically\n",[294,5043,5044],{"class":296,"line":432},[294,5045,5046],{"class":300},"# No manual intervention needed -- scales based on actual demand\n",[14,5048,5050],{"id":5049},"what-modern-infrastructure-looks-like","What Modern Infrastructure Looks Like",[19,5052,5053],{},"If you recognised your business in one or more of the signs above, you are not alone. Most growing businesses reach this inflection point. The question is what to do about it.",[19,5055,5056],{},"Modern infrastructure is built on a set of principles that address each of the problems described above.",[79,5058,5060],{"id":5059},"containers-and-orchestration","Containers and Orchestration",[19,5062,5063],{},"Containers (Docker) package your application with its dependencies, ensuring consistency from development to production. Kubernetes orchestrates those containers at scale, handling scheduling, scaling, health checks, and self-healing automatically.",[79,5065,5067],{"id":5066},"infrastructure-as-code-iac","Infrastructure as Code (IaC)",[19,5069,5070],{},"Every piece of infrastructure -- servers, databases, networks, load balancers -- is defined in code (Terraform, Pulumi, CloudFormation) and version-controlled. This eliminates manual configuration, enables reproducible environments, and makes infrastructure changes reviewable and auditable.",[79,5072,5074],{"id":5073},"gitops-workflows","GitOps Workflows",[19,5076,5077],{},"Infrastructure changes follow the same workflow as code changes: propose a change via pull request, review it, merge it, and let automation apply it. This brings engineering best practices -- code review, version history, rollback capability -- to infrastructure management.",[79,5079,5081],{"id":5080},"comprehensive-observability","Comprehensive Observability",[19,5083,5084],{},"Centralised logging, metrics, and distributed tracing give your team real-time visibility into system behaviour. Intelligent alerting notifies the right people about the right problems, and dashboards provide at-a-glance system health views.",[79,5086,5088],{"id":5087},"automated-scaling-and-self-healing","Automated Scaling and Self-Healing",[19,5090,5091],{},"Horizontal auto-scaling adjusts capacity based on actual demand. Health checks and readiness probes detect unhealthy instances and replace them automatically. Circuit breakers and retry policies prevent cascading failures.",[1162,5093,5094],{"type":322},[19,5095,5096],{},"You do not need to implement all of these at once. Start with the sign that is causing the most pain in your business today. For most companies, that is either the deployment pipeline (Sign 1) or observability (Sign 4). These two improvements alone can transform your engineering team's effectiveness.",[14,5098,5100],{"id":5099},"taking-the-first-step","Taking the First Step",[19,5102,5103],{},"Modernising your infrastructure is not a single project -- it is a journey. The worst approach is to attempt a \"big bang\" migration where you rebuild everything at once. The best approach is incremental: identify the highest-impact problem, solve it, measure the improvement, and move on to the next one.",[19,5105,5106],{},"If you are unsure where to start, an infrastructure assessment can map your current state, identify the most critical gaps, and create a prioritised roadmap that delivers value at each stage rather than deferring all value to the end of a multi-month project.",[19,5108,5109],{},"The businesses that modernise their infrastructure proactively -- before a crisis forces their hand -- spend less, move faster, and build more resilient systems. The ones that wait until infrastructure is actively impeding the business always wish they had started sooner.",[2357,5111],{},[19,5113,5114],{},[2180,5115,5116,5117,5120,5121,5124,5125,5128],{},"Get a free infrastructure assessment from our cloud architects. ",[230,5118,5119],{"href":2366},"Contact us"," to discuss how our ",[230,5122,5123],{"href":2015},"cloud-native"," and ",[230,5126,5127],{"href":3798},"platform engineering"," teams can help you modernise your infrastructure without disrupting your business.",[2370,5130,5131],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":289,"searchDepth":304,"depth":304,"links":5133},[5134,5135,5140,5145,5150,5155,5160,5167],{"id":3634,"depth":304,"text":3635},{"id":3652,"depth":304,"text":3653,"children":5136},[5137,5138,5139],{"id":3659,"depth":319,"text":3660},{"id":3680,"depth":319,"text":3681},{"id":3788,"depth":319,"text":3789},{"id":3808,"depth":304,"text":3809,"children":5141},[5142,5143,5144],{"id":3815,"depth":319,"text":3660},{"id":3835,"depth":319,"text":3681},{"id":3847,"depth":319,"text":3789},{"id":4142,"depth":304,"text":4143,"children":5146},[5147,5148,5149],{"id":4149,"depth":319,"text":3660},{"id":4169,"depth":319,"text":3681},{"id":4178,"depth":319,"text":3789},{"id":4716,"depth":304,"text":4717,"children":5151},[5152,5153,5154],{"id":4723,"depth":319,"text":3660},{"id":4743,"depth":319,"text":3681},{"id":4759,"depth":319,"text":3789},{"id":4897,"depth":304,"text":4898,"children":5156},[5157,5158,5159],{"id":4904,"depth":319,"text":3660},{"id":4924,"depth":319,"text":3681},{"id":4933,"depth":319,"text":3789},{"id":5049,"depth":304,"text":5050,"children":5161},[5162,5163,5164,5165,5166],{"id":5059,"depth":319,"text":5060},{"id":5066,"depth":319,"text":5067},{"id":5073,"depth":319,"text":5074},{"id":5080,"depth":319,"text":5081},{"id":5087,"depth":319,"text":5088},{"id":5099,"depth":304,"text":5100},"Cloud","2026-01-21","Slow deployments, rising cloud bills, and weekend outages are symptoms of infrastructure that cannot keep pace. Here are 5 signs it is time to modernise.",{},"/blog/signs-outgrown-infrastructure","7 min read",{"title":3628,"description":5170},"blog/signs-outgrown-infrastructure",[5177,5178,5179,5180],"Cloud Migration","Infrastructure","Scalability","DevOps","YUbVbTZRcQ3Th3ipiH62RKS-m6mixBXsJ4Z_pMOFAu0",[5183,6973,7896],{"id":5,"title":6,"author":5184,"body":5185,"category":2406,"coverImage":2407,"date":2408,"description":2409,"extension":2410,"featured":2411,"meta":6970,"navigation":365,"path":2413,"readingTime":2414,"seo":6971,"stem":2416,"tags":6972,"__hash__":2421},{"name":8,"role":9},{"type":11,"value":5186,"toc":6937},[5187,5189,5193,5195,5199,5201,5203,5205,5219,5221,5223,5225,5227,5231,5235,5237,5241,5245,5247,5251,5255,5317,5319,5321,5323,5325,5329,5331,5333,5335,5339,5343,5345,5347,5349,5351,5353,5355,5967,5969,5971,5973,6019,6021,6027,6029,6031,6423,6425,6427,6429,6437,6443,6449,6451,6461,6463,6465,6621,6623,6637,6641,6643,6645,6647,6677,6681,6683,6685,6687,6689,6691,6699,6701,6703,6791,6793,6795,6799,6801,6805,6893,6895,6897,6899,6921,6923,6927,6929,6935],[14,5188,17],{"id":16},[19,5190,21,5191,26],{},[23,5192,25],{},[19,5194,29],{},[31,5196,5197],{},[19,5198,35],{},[14,5200,39],{"id":38},[19,5202,42],{},[19,5204,45],{},[47,5206,5207,5209,5211,5213,5215,5217],{},[50,5208,52],{},[50,5210,55],{},[50,5212,58],{},[50,5214,61],{},[50,5216,64],{},[50,5218,67],{},[19,5220,70],{},[14,5222,74],{"id":73},[19,5224,77],{},[79,5226,82],{"id":81},[19,5228,5229,88],{},[23,5230,87],{},[19,5232,5233,94],{},[23,5234,93],{},[79,5236,98],{"id":97},[19,5238,5239,103],{},[23,5240,87],{},[19,5242,5243,108],{},[23,5244,93],{},[79,5246,112],{"id":111},[19,5248,5249,117],{},[23,5250,87],{},[19,5252,5253,122],{},[23,5254,93],{},[124,5256,5257,5267],{},[127,5258,5259],{},[130,5260,5261,5263,5265],{},[133,5262,135],{},[133,5264,138],{},[133,5266,141],{},[143,5268,5269,5277,5285,5293,5301,5309],{},[130,5270,5271,5273,5275],{},[148,5272,150],{},[148,5274,153],{},[148,5276,156],{},[130,5278,5279,5281,5283],{},[148,5280,161],{},[148,5282,164],{},[148,5284,167],{},[130,5286,5287,5289,5291],{},[148,5288,172],{},[148,5290,175],{},[148,5292,178],{},[130,5294,5295,5297,5299],{},[148,5296,183],{},[148,5298,186],{},[148,5300,189],{},[130,5302,5303,5305,5307],{},[148,5304,194],{},[148,5306,197],{},[148,5308,200],{},[130,5310,5311,5313,5315],{},[148,5312,205],{},[148,5314,208],{},[148,5316,211],{},[14,5318,215],{"id":214},[19,5320,218],{},[79,5322,222],{"id":221},[19,5324,225],{},[19,5326,228,5327,234],{},[230,5328,233],{"href":232},[79,5330,238],{"id":237},[19,5332,241],{},[79,5334,245],{"id":244},[19,5336,248,5337,253],{},[230,5338,252],{"href":251},[19,5340,256,5341,261],{},[230,5342,260],{"href":259},[79,5344,265],{"id":264},[19,5346,268],{},[14,5348,272],{"id":271},[19,5350,275],{},[79,5352,279],{"id":278},[19,5354,282],{},[284,5356,5357],{"className":286,"code":287,"language":288,"meta":289,"style":289},[291,5358,5359,5363,5371,5377,5385,5393,5401,5405,5411,5417,5423,5431,5439,5445,5451,5457,5465,5471,5477,5483,5491,5497,5503,5511,5517,5523,5529,5537,5543,5551,5557,5563,5569,5577,5583,5591,5597,5603,5609,5617,5621,5627,5633,5639,5647,5653,5659,5665,5671,5677,5683,5689,5697,5703,5709,5715,5721,5727,5735,5743,5751,5757,5765,5773,5781,5787,5795,5803,5809,5817,5825,5829,5835,5843,5849,5855,5863,5871,5877,5885,5891,5897,5903,5909,5915,5923,5929,5937,5945,5951,5959],{"__ignoreMap":289},[294,5360,5361],{"class":296,"line":297},[294,5362,301],{"class":300},[294,5364,5365,5367,5369],{"class":296,"line":304},[294,5366,308],{"class":307},[294,5368,312],{"class":311},[294,5370,316],{"class":315},[294,5372,5373,5375],{"class":296,"line":319},[294,5374,322],{"class":307},[294,5376,325],{"class":311},[294,5378,5379,5381,5383],{"class":296,"line":328},[294,5380,331],{"class":307},[294,5382,312],{"class":311},[294,5384,337],{"class":336},[294,5386,5387,5389,5391],{"class":296,"line":340},[294,5388,343],{"class":307},[294,5390,312],{"class":311},[294,5392,348],{"class":315},[294,5394,5395,5397,5399],{"class":296,"line":351},[294,5396,354],{"class":307},[294,5398,312],{"class":311},[294,5400,359],{"class":336},[294,5402,5403],{"class":296,"line":362},[294,5404,366],{"emptyLinePlaceholder":365},[294,5406,5407,5409],{"class":296,"line":369},[294,5408,372],{"class":307},[294,5410,325],{"class":311},[294,5412,5413,5415],{"class":296,"line":377},[294,5414,380],{"class":307},[294,5416,325],{"class":311},[294,5418,5419,5421],{"class":296,"line":385},[294,5420,388],{"class":307},[294,5422,325],{"class":311},[294,5424,5425,5427,5429],{"class":296,"line":393},[294,5426,396],{"class":307},[294,5428,312],{"class":311},[294,5430,401],{"class":336},[294,5432,5433,5435,5437],{"class":296,"line":404},[294,5434,407],{"class":307},[294,5436,312],{"class":311},[294,5438,412],{"class":336},[294,5440,5441,5443],{"class":296,"line":415},[294,5442,418],{"class":307},[294,5444,325],{"class":311},[294,5446,5447,5449],{"class":296,"line":423},[294,5448,426],{"class":311},[294,5450,429],{"class":336},[294,5452,5453,5455],{"class":296,"line":432},[294,5454,435],{"class":307},[294,5456,325],{"class":311},[294,5458,5459,5461,5463],{"class":296,"line":440},[294,5460,443],{"class":307},[294,5462,312],{"class":311},[294,5464,448],{"class":315},[294,5466,5467,5469],{"class":296,"line":451},[294,5468,454],{"class":307},[294,5470,325],{"class":311},[294,5472,5473,5475],{"class":296,"line":459},[294,5474,462],{"class":307},[294,5476,325],{"class":311},[294,5478,5479,5481],{"class":296,"line":467},[294,5480,470],{"class":307},[294,5482,325],{"class":311},[294,5484,5485,5487,5489],{"class":296,"line":475},[294,5486,478],{"class":307},[294,5488,312],{"class":311},[294,5490,483],{"class":336},[294,5492,5493,5495],{"class":296,"line":486},[294,5494,489],{"class":307},[294,5496,325],{"class":311},[294,5498,5499,5501],{"class":296,"line":494},[294,5500,497],{"class":336},[294,5502,325],{"class":311},[294,5504,5505,5507,5509],{"class":296,"line":502},[294,5506,505],{"class":307},[294,5508,312],{"class":311},[294,5510,510],{"class":336},[294,5512,5513,5515],{"class":296,"line":513},[294,5514,516],{"class":307},[294,5516,325],{"class":311},[294,5518,5519,5521],{"class":296,"line":521},[294,5520,524],{"class":307},[294,5522,325],{"class":311},[294,5524,5525,5527],{"class":296,"line":529},[294,5526,532],{"class":307},[294,5528,325],{"class":311},[294,5530,5531,5533,5535],{"class":296,"line":537},[294,5532,540],{"class":307},[294,5534,312],{"class":311},[294,5536,545],{"class":336},[294,5538,5539,5541],{"class":296,"line":548},[294,5540,551],{"class":336},[294,5542,325],{"class":311},[294,5544,5545,5547,5549],{"class":296,"line":556},[294,5546,505],{"class":307},[294,5548,312],{"class":311},[294,5550,563],{"class":336},[294,5552,5553,5555],{"class":296,"line":566},[294,5554,516],{"class":307},[294,5556,325],{"class":311},[294,5558,5559,5561],{"class":296,"line":573},[294,5560,524],{"class":307},[294,5562,325],{"class":311},[294,5564,5565,5567],{"class":296,"line":580},[294,5566,532],{"class":307},[294,5568,325],{"class":311},[294,5570,5571,5573,5575],{"class":296,"line":587},[294,5572,540],{"class":307},[294,5574,312],{"class":311},[294,5576,594],{"class":336},[294,5578,5579,5581],{"class":296,"line":597},[294,5580,600],{"class":336},[294,5582,325],{"class":311},[294,5584,5585,5587,5589],{"class":296,"line":605},[294,5586,505],{"class":307},[294,5588,312],{"class":311},[294,5590,612],{"class":336},[294,5592,5593,5595],{"class":296,"line":615},[294,5594,516],{"class":307},[294,5596,325],{"class":311},[294,5598,5599,5601],{"class":296,"line":622},[294,5600,524],{"class":307},[294,5602,325],{"class":311},[294,5604,5605,5607],{"class":296,"line":629},[294,5606,532],{"class":307},[294,5608,325],{"class":311},[294,5610,5611,5613,5615],{"class":296,"line":636},[294,5612,540],{"class":307},[294,5614,312],{"class":311},[294,5616,643],{"class":336},[294,5618,5619],{"class":296,"line":646},[294,5620,366],{"emptyLinePlaceholder":365},[294,5622,5623,5625],{"class":296,"line":651},[294,5624,654],{"class":307},[294,5626,325],{"class":311},[294,5628,5629,5631],{"class":296,"line":659},[294,5630,662],{"class":307},[294,5632,325],{"class":311},[294,5634,5635,5637],{"class":296,"line":667},[294,5636,670],{"class":307},[294,5638,325],{"class":311},[294,5640,5641,5643,5645],{"class":296,"line":675},[294,5642,678],{"class":307},[294,5644,312],{"class":311},[294,5646,683],{"class":336},[294,5648,5649,5651],{"class":296,"line":686},[294,5650,689],{"class":307},[294,5652,325],{"class":311},[294,5654,5655,5657],{"class":296,"line":694},[294,5656,426],{"class":311},[294,5658,699],{"class":336},[294,5660,5661,5663],{"class":296,"line":702},[294,5662,426],{"class":311},[294,5664,707],{"class":336},[294,5666,5667,5669],{"class":296,"line":710},[294,5668,426],{"class":311},[294,5670,715],{"class":336},[294,5672,5673,5675],{"class":296,"line":718},[294,5674,426],{"class":311},[294,5676,723],{"class":336},[294,5678,5679,5681],{"class":296,"line":726},[294,5680,729],{"class":307},[294,5682,325],{"class":311},[294,5684,5685,5687],{"class":296,"line":734},[294,5686,737],{"class":307},[294,5688,325],{"class":311},[294,5690,5691,5693,5695],{"class":296,"line":742},[294,5692,745],{"class":307},[294,5694,312],{"class":311},[294,5696,750],{"class":336},[294,5698,5699,5701],{"class":296,"line":753},[294,5700,756],{"class":307},[294,5702,325],{"class":311},[294,5704,5705,5707],{"class":296,"line":761},[294,5706,764],{"class":311},[294,5708,767],{"class":336},[294,5710,5711,5713],{"class":296,"line":770},[294,5712,764],{"class":311},[294,5714,775],{"class":336},[294,5716,5717,5719],{"class":296,"line":778},[294,5718,764],{"class":311},[294,5720,783],{"class":336},[294,5722,5723,5725],{"class":296,"line":786},[294,5724,789],{"class":307},[294,5726,325],{"class":311},[294,5728,5729,5731,5733],{"class":296,"line":794},[294,5730,745],{"class":307},[294,5732,312],{"class":311},[294,5734,750],{"class":336},[294,5736,5737,5739,5741],{"class":296,"line":803},[294,5738,806],{"class":307},[294,5740,312],{"class":311},[294,5742,811],{"class":336},[294,5744,5745,5747,5749],{"class":296,"line":814},[294,5746,505],{"class":307},[294,5748,312],{"class":311},[294,5750,821],{"class":336},[294,5752,5753,5755],{"class":296,"line":824},[294,5754,827],{"class":307},[294,5756,325],{"class":311},[294,5758,5759,5761,5763],{"class":296,"line":832},[294,5760,745],{"class":307},[294,5762,312],{"class":311},[294,5764,750],{"class":336},[294,5766,5767,5769,5771],{"class":296,"line":841},[294,5768,844],{"class":307},[294,5770,312],{"class":311},[294,5772,849],{"class":315},[294,5774,5775,5777,5779],{"class":296,"line":852},[294,5776,855],{"class":307},[294,5778,312],{"class":311},[294,5780,860],{"class":315},[294,5782,5783,5785],{"class":296,"line":863},[294,5784,866],{"class":307},[294,5786,325],{"class":311},[294,5788,5789,5791,5793],{"class":296,"line":871},[294,5790,745],{"class":307},[294,5792,312],{"class":311},[294,5794,750],{"class":336},[294,5796,5797,5799,5801],{"class":296,"line":880},[294,5798,806],{"class":307},[294,5800,312],{"class":311},[294,5802,887],{"class":336},[294,5804,5805,5807],{"class":296,"line":890},[294,5806,893],{"class":307},[294,5808,325],{"class":311},[294,5810,5811,5813,5815],{"class":296,"line":898},[294,5812,745],{"class":307},[294,5814,312],{"class":311},[294,5816,750],{"class":336},[294,5818,5819,5821,5823],{"class":296,"line":907},[294,5820,855],{"class":307},[294,5822,312],{"class":311},[294,5824,914],{"class":315},[294,5826,5827],{"class":296,"line":917},[294,5828,366],{"emptyLinePlaceholder":365},[294,5830,5831,5833],{"class":296,"line":922},[294,5832,925],{"class":307},[294,5834,325],{"class":311},[294,5836,5837,5839,5841],{"class":296,"line":930},[294,5838,678],{"class":307},[294,5840,312],{"class":311},[294,5842,683],{"class":336},[294,5844,5845,5847],{"class":296,"line":939},[294,5846,729],{"class":307},[294,5848,325],{"class":311},[294,5850,5851,5853],{"class":296,"line":946},[294,5852,949],{"class":307},[294,5854,325],{"class":311},[294,5856,5857,5859,5861],{"class":296,"line":954},[294,5858,745],{"class":307},[294,5860,312],{"class":311},[294,5862,750],{"class":336},[294,5864,5865,5867,5869],{"class":296,"line":963},[294,5866,806],{"class":307},[294,5868,312],{"class":311},[294,5870,970],{"class":336},[294,5872,5873,5875],{"class":296,"line":973},[294,5874,976],{"class":307},[294,5876,325],{"class":311},[294,5878,5879,5881,5883],{"class":296,"line":981},[294,5880,745],{"class":307},[294,5882,312],{"class":311},[294,5884,750],{"class":336},[294,5886,5887,5889],{"class":296,"line":990},[294,5888,756],{"class":307},[294,5890,325],{"class":311},[294,5892,5893,5895],{"class":296,"line":997},[294,5894,764],{"class":311},[294,5896,1002],{"class":336},[294,5898,5899,5901],{"class":296,"line":1005},[294,5900,764],{"class":311},[294,5902,1010],{"class":336},[294,5904,5905,5907],{"class":296,"line":1013},[294,5906,764],{"class":311},[294,5908,1018],{"class":336},[294,5910,5911,5913],{"class":296,"line":1021},[294,5912,737],{"class":307},[294,5914,325],{"class":311},[294,5916,5917,5919,5921],{"class":296,"line":1028},[294,5918,745],{"class":307},[294,5920,312],{"class":311},[294,5922,750],{"class":336},[294,5924,5925,5927],{"class":296,"line":1037},[294,5926,789],{"class":307},[294,5928,325],{"class":311},[294,5930,5931,5933,5935],{"class":296,"line":1044},[294,5932,745],{"class":307},[294,5934,312],{"class":311},[294,5936,750],{"class":336},[294,5938,5939,5941,5943],{"class":296,"line":1053},[294,5940,806],{"class":307},[294,5942,312],{"class":311},[294,5944,811],{"class":336},[294,5946,5947,5949],{"class":296,"line":1062},[294,5948,1065],{"class":307},[294,5950,325],{"class":311},[294,5952,5953,5955,5957],{"class":296,"line":1070},[294,5954,745],{"class":307},[294,5956,312],{"class":311},[294,5958,750],{"class":336},[294,5960,5961,5963,5965],{"class":296,"line":1079},[294,5962,806],{"class":307},[294,5964,312],{"class":311},[294,5966,811],{"class":336},[19,5968,1088],{},[79,5970,1092],{"id":1091},[19,5972,1095],{},[284,5974,5975],{"className":1098,"code":1099,"language":1100,"meta":289,"style":289},[291,5976,5977,5981,5995,5999,6003,6007],{"__ignoreMap":289},[294,5978,5979],{"class":296,"line":297},[294,5980,1107],{"class":300},[294,5982,5983,5985,5987,5989,5991,5993],{"class":296,"line":304},[294,5984,1113],{"class":1112},[294,5986,1116],{"class":336},[294,5988,1119],{"class":336},[294,5990,1122],{"class":336},[294,5992,1125],{"class":315},[294,5994,1128],{"class":315},[294,5996,5997],{"class":296,"line":319},[294,5998,366],{"emptyLinePlaceholder":365},[294,6000,6001],{"class":296,"line":328},[294,6002,1137],{"class":300},[294,6004,6005],{"class":296,"line":340},[294,6006,1142],{"class":300},[294,6008,6009,6011,6013,6015,6017],{"class":296,"line":351},[294,6010,1113],{"class":1112},[294,6012,1149],{"class":336},[294,6014,1122],{"class":336},[294,6016,1154],{"class":315},[294,6018,1157],{"class":336},[19,6020,1160],{},[1162,6022,6023],{"type":1164},[19,6024,1167,6025,1171],{},[291,6026,1170],{},[79,6028,1175],{"id":1174},[19,6030,1178],{},[284,6032,6033],{"className":1181,"code":1182,"language":1183,"meta":289,"style":289},[291,6034,6035,6039,6051,6055,6069,6077,6085,6089,6093,6107,6125,6131,6139,6151,6163,6187,6191,6207,6215,6223,6231,6239,6247,6251,6255,6275,6283,6295,6303,6311,6319,6323,6327,6347,6361,6369,6377,6385,6393,6397,6411,6415,6419],{"__ignoreMap":289},[294,6036,6037],{"class":296,"line":297},[294,6038,1190],{"class":300},[294,6040,6041,6043,6045,6047,6049],{"class":296,"line":304},[294,6042,1196],{"class":1195},[294,6044,1199],{"class":311},[294,6046,1202],{"class":1195},[294,6048,1205],{"class":336},[294,6050,1208],{"class":311},[294,6052,6053],{"class":296,"line":319},[294,6054,366],{"emptyLinePlaceholder":365},[294,6056,6057,6059,6061,6063,6065,6067],{"class":296,"line":328},[294,6058,1217],{"class":1195},[294,6060,1220],{"class":315},[294,6062,1223],{"class":1195},[294,6064,1226],{"class":1195},[294,6066,1229],{"class":1112},[294,6068,1232],{"class":311},[294,6070,6071,6073,6075],{"class":296,"line":340},[294,6072,1237],{"class":311},[294,6074,1240],{"class":336},[294,6076,1243],{"class":311},[294,6078,6079,6081,6083],{"class":296,"line":351},[294,6080,1248],{"class":311},[294,6082,1251],{"class":336},[294,6084,1243],{"class":311},[294,6086,6087],{"class":296,"line":362},[294,6088,1258],{"class":311},[294,6090,6091],{"class":296,"line":369},[294,6092,366],{"emptyLinePlaceholder":365},[294,6094,6095,6097,6099,6101,6103,6105],{"class":296,"line":377},[294,6096,1267],{"class":1112},[294,6098,1270],{"class":311},[294,6100,1273],{"class":336},[294,6102,1276],{"class":311},[294,6104,1279],{"class":1195},[294,6106,1282],{"class":311},[294,6108,6109,6111,6113,6115,6117,6119,6121,6123],{"class":296,"line":385},[294,6110,1287],{"class":1112},[294,6112,1270],{"class":311},[294,6114,1292],{"class":336},[294,6116,1295],{"class":311},[294,6118,1298],{"class":1195},[294,6120,1301],{"class":311},[294,6122,1279],{"class":1195},[294,6124,1282],{"class":311},[294,6126,6127,6129],{"class":296,"line":393},[294,6128,1310],{"class":1195},[294,6130,1313],{"class":311},[294,6132,6133,6135,6137],{"class":296,"line":404},[294,6134,1318],{"class":311},[294,6136,1321],{"class":1112},[294,6138,1324],{"class":311},[294,6140,6141,6143,6145,6147,6149],{"class":296,"line":415},[294,6142,1318],{"class":311},[294,6144,1331],{"class":1112},[294,6146,1270],{"class":311},[294,6148,1336],{"class":336},[294,6150,1339],{"class":311},[294,6152,6153,6155,6157,6159,6161],{"class":296,"line":423},[294,6154,1318],{"class":311},[294,6156,1346],{"class":1112},[294,6158,1270],{"class":311},[294,6160,1351],{"class":336},[294,6162,1339],{"class":311},[294,6164,6165,6167,6169,6171,6173,6175,6177,6179,6181,6183,6185],{"class":296,"line":432},[294,6166,1318],{"class":311},[294,6168,1360],{"class":1112},[294,6170,1270],{"class":311},[294,6172,1365],{"class":336},[294,6174,1295],{"class":311},[294,6176,1370],{"class":336},[294,6178,1373],{"class":311},[294,6180,1377],{"class":1376},[294,6182,1380],{"class":311},[294,6184,1279],{"class":1195},[294,6186,1282],{"class":311},[294,6188,6189],{"class":296,"line":440},[294,6190,1389],{"class":311},[294,6192,6193,6195,6197,6199,6201,6203,6205],{"class":296,"line":451},[294,6194,1394],{"class":311},[294,6196,1397],{"class":1112},[294,6198,1400],{"class":311},[294,6200,1403],{"class":336},[294,6202,312],{"class":311},[294,6204,1408],{"class":336},[294,6206,1411],{"class":311},[294,6208,6209,6211,6213],{"class":296,"line":459},[294,6210,1394],{"class":311},[294,6212,1418],{"class":1112},[294,6214,1232],{"class":311},[294,6216,6217,6219,6221],{"class":296,"line":467},[294,6218,1425],{"class":311},[294,6220,1428],{"class":336},[294,6222,1243],{"class":311},[294,6224,6225,6227,6229],{"class":296,"line":475},[294,6226,1435],{"class":311},[294,6228,1438],{"class":336},[294,6230,1243],{"class":311},[294,6232,6233,6235,6237],{"class":296,"line":486},[294,6234,1445],{"class":311},[294,6236,1448],{"class":336},[294,6238,1243],{"class":311},[294,6240,6241,6243,6245],{"class":296,"line":494},[294,6242,1455],{"class":311},[294,6244,1458],{"class":336},[294,6246,1243],{"class":311},[294,6248,6249],{"class":296,"line":502},[294,6250,1465],{"class":311},[294,6252,6253],{"class":296,"line":513},[294,6254,1470],{"class":311},[294,6256,6257,6259,6261,6263,6265,6267,6269,6271,6273],{"class":296,"line":521},[294,6258,1318],{"class":311},[294,6260,1477],{"class":1112},[294,6262,1270],{"class":311},[294,6264,1482],{"class":315},[294,6266,1373],{"class":311},[294,6268,1377],{"class":1376},[294,6270,1380],{"class":311},[294,6272,1279],{"class":1195},[294,6274,1282],{"class":311},[294,6276,6277,6279,6281],{"class":296,"line":529},[294,6278,1497],{"class":311},[294,6280,1418],{"class":1112},[294,6282,1232],{"class":311},[294,6284,6285,6287,6289,6291,6293],{"class":296,"line":537},[294,6286,1506],{"class":311},[294,6288,1509],{"class":1112},[294,6290,1270],{"class":311},[294,6292,1514],{"class":336},[294,6294,1517],{"class":311},[294,6296,6297,6299,6301],{"class":296,"line":548},[294,6298,1522],{"class":311},[294,6300,1525],{"class":336},[294,6302,1243],{"class":311},[294,6304,6305,6307,6309],{"class":296,"line":556},[294,6306,1532],{"class":311},[294,6308,1428],{"class":336},[294,6310,1243],{"class":311},[294,6312,6313,6315,6317],{"class":296,"line":566},[294,6314,1541],{"class":311},[294,6316,1438],{"class":336},[294,6318,1243],{"class":311},[294,6320,6321],{"class":296,"line":573},[294,6322,1550],{"class":311},[294,6324,6325],{"class":296,"line":580},[294,6326,1470],{"class":311},[294,6328,6329,6331,6333,6335,6337,6339,6341,6343,6345],{"class":296,"line":587},[294,6330,1318],{"class":311},[294,6332,1561],{"class":1112},[294,6334,1270],{"class":311},[294,6336,1298],{"class":1195},[294,6338,1568],{"class":311},[294,6340,1571],{"class":1376},[294,6342,1380],{"class":311},[294,6344,1279],{"class":1195},[294,6346,1282],{"class":311},[294,6348,6349,6351,6353,6355,6357,6359],{"class":296,"line":597},[294,6350,1582],{"class":1195},[294,6352,1585],{"class":315},[294,6354,1223],{"class":1195},[294,6356,1590],{"class":1195},[294,6358,1593],{"class":1112},[294,6360,1596],{"class":311},[294,6362,6363,6365,6367],{"class":296,"line":605},[294,6364,1532],{"class":311},[294,6366,1428],{"class":336},[294,6368,1243],{"class":311},[294,6370,6371,6373,6375],{"class":296,"line":615},[294,6372,1541],{"class":311},[294,6374,1438],{"class":336},[294,6376,1243],{"class":311},[294,6378,6379,6381,6383],{"class":296,"line":622},[294,6380,1617],{"class":311},[294,6382,1448],{"class":336},[294,6384,1243],{"class":311},[294,6386,6387,6389,6391],{"class":296,"line":629},[294,6388,1626],{"class":311},[294,6390,1458],{"class":336},[294,6392,1243],{"class":311},[294,6394,6395],{"class":296,"line":636},[294,6396,1550],{"class":311},[294,6398,6399,6401,6403,6405,6407,6409],{"class":296,"line":646},[294,6400,1639],{"class":1112},[294,6402,1642],{"class":311},[294,6404,1645],{"class":1112},[294,6406,1270],{"class":311},[294,6408,1525],{"class":336},[294,6410,1652],{"class":311},[294,6412,6413],{"class":296,"line":651},[294,6414,1657],{"class":311},[294,6416,6417],{"class":296,"line":659},[294,6418,1662],{"class":311},[294,6420,6421],{"class":296,"line":667},[294,6422,1258],{"class":311},[19,6424,1669],{},[79,6426,1673],{"id":1672},[19,6428,1676],{},[19,6430,6431,1568,6433,1295,6435,1688],{},[23,6432,1681],{},[291,6434,1684],{},[291,6436,1687],{},[19,6438,6439,1568,6441,1697],{},[23,6440,1693],{},[291,6442,1696],{},[19,6444,6445,1568,6447,1706],{},[23,6446,1702],{},[291,6448,1705],{},[19,6450,1709],{},[1711,6452,6453,6455,6457,6459],{},[50,6454,1715],{},[50,6456,1718],{},[50,6458,1721],{},[50,6460,1724],{},[79,6462,1728],{"id":1727},[19,6464,1731],{},[284,6466,6467],{"className":1181,"code":1734,"language":1183,"meta":289,"style":289},[291,6468,6469,6473,6485,6489,6501,6515,6525,6547,6565,6581,6589,6597,6609,6613,6617],{"__ignoreMap":289},[294,6470,6471],{"class":296,"line":297},[294,6472,1741],{"class":300},[294,6474,6475,6477,6479,6481,6483],{"class":296,"line":304},[294,6476,1196],{"class":1195},[294,6478,1748],{"class":311},[294,6480,1202],{"class":1195},[294,6482,1753],{"class":336},[294,6484,1208],{"class":311},[294,6486,6487],{"class":296,"line":319},[294,6488,366],{"emptyLinePlaceholder":365},[294,6490,6491,6493,6495,6497,6499],{"class":296,"line":328},[294,6492,1217],{"class":1195},[294,6494,1766],{"class":315},[294,6496,1223],{"class":1195},[294,6498,1771],{"class":1112},[294,6500,1232],{"class":311},[294,6502,6503,6505,6507,6509,6511,6513],{"class":296,"line":340},[294,6504,1778],{"class":311},[294,6506,1781],{"class":315},[294,6508,1784],{"class":1195},[294,6510,1787],{"class":315},[294,6512,1295],{"class":311},[294,6514,1792],{"class":300},[294,6516,6517,6519,6521,6523],{"class":296,"line":351},[294,6518,1797],{"class":311},[294,6520,1800],{"class":315},[294,6522,1803],{"class":311},[294,6524,1806],{"class":300},[294,6526,6527,6529,6531,6533,6535,6537,6539,6541,6543,6545],{"class":296,"line":362},[294,6528,1811],{"class":1112},[294,6530,1814],{"class":311},[294,6532,1817],{"class":1376},[294,6534,1380],{"class":311},[294,6536,1279],{"class":1195},[294,6538,1824],{"class":311},[294,6540,1827],{"class":336},[294,6542,1830],{"class":311},[294,6544,1833],{"class":1195},[294,6546,1836],{"class":311},[294,6548,6549,6551,6553,6555,6557,6559,6561,6563],{"class":296,"line":369},[294,6550,1841],{"class":1112},[294,6552,1814],{"class":311},[294,6554,1817],{"class":1376},[294,6556,1295],{"class":311},[294,6558,1850],{"class":1376},[294,6560,1380],{"class":311},[294,6562,1279],{"class":1195},[294,6564,1282],{"class":311},[294,6566,6567,6569,6571,6573,6575,6577,6579],{"class":296,"line":377},[294,6568,1861],{"class":311},[294,6570,1864],{"class":1112},[294,6572,1270],{"class":311},[294,6574,1869],{"class":315},[294,6576,1872],{"class":311},[294,6578,1875],{"class":1112},[294,6580,1232],{"class":311},[294,6582,6583,6585,6587],{"class":296,"line":385},[294,6584,1882],{"class":311},[294,6586,1885],{"class":336},[294,6588,1243],{"class":311},[294,6590,6591,6593,6595],{"class":296,"line":393},[294,6592,1892],{"class":311},[294,6594,1895],{"class":336},[294,6596,1243],{"class":311},[294,6598,6599,6601,6603,6605,6607],{"class":296,"line":404},[294,6600,1902],{"class":311},[294,6602,1905],{"class":1112},[294,6604,1270],{"class":311},[294,6606,1910],{"class":336},[294,6608,1517],{"class":311},[294,6610,6611],{"class":296,"line":415},[294,6612,1917],{"class":311},[294,6614,6615],{"class":296,"line":423},[294,6616,1922],{"class":311},[294,6618,6619],{"class":296,"line":432},[294,6620,1258],{"class":311},[19,6622,1929],{},[1711,6624,6625,6629,6633],{},[50,6626,6627,1937],{},[23,6628,1936],{},[50,6630,6631,1943],{},[23,6632,1942],{},[50,6634,6635,1949],{},[23,6636,1948],{},[1162,6638,6639],{"type":322},[19,6640,1954],{},[14,6642,1958],{"id":1957},[19,6644,1961],{},[79,6646,1965],{"id":1964},[1711,6648,6649,6653,6657,6661,6665,6669,6673],{},[50,6650,6651,1973],{},[23,6652,1972],{},[50,6654,6655,1979],{},[23,6656,1978],{},[50,6658,6659,1985],{},[23,6660,1984],{},[50,6662,6663,1991],{},[23,6664,1990],{},[50,6666,6667,1997],{},[23,6668,1996],{},[50,6670,6671,2003],{},[23,6672,2002],{},[50,6674,6675,2009],{},[23,6676,2008],{},[19,6678,2012,6679,2017],{},[230,6680,2016],{"href":2015},[14,6682,2021],{"id":2020},[19,6684,2024],{},[79,6686,2028],{"id":2027},[19,6688,2031],{},[79,6690,2035],{"id":2034},[19,6692,2038,6693,2042,6695,2046,6697,2050],{},[291,6694,2041],{},[291,6696,2045],{},[291,6698,2049],{},[79,6700,2054],{"id":2053},[19,6702,2057],{},[284,6704,6705],{"className":1181,"code":2060,"language":1183,"meta":289,"style":289},[291,6706,6707,6711,6723,6733,6741,6755,6765,6775,6779,6783,6787],{"__ignoreMap":289},[294,6708,6709],{"class":296,"line":297},[294,6710,2067],{"class":300},[294,6712,6713,6715,6717,6719,6721],{"class":296,"line":304},[294,6714,2072],{"class":1195},[294,6716,2075],{"class":1112},[294,6718,2078],{"class":311},[294,6720,2081],{"class":1112},[294,6722,2084],{"class":311},[294,6724,6725,6727,6729,6731],{"class":296,"line":319},[294,6726,2089],{"class":1376},[294,6728,2092],{"class":1195},[294,6730,2095],{"class":1112},[294,6732,2098],{"class":311},[294,6734,6735,6737,6739],{"class":296,"line":328},[294,6736,2103],{"class":1376},[294,6738,2092],{"class":1195},[294,6740,1282],{"class":311},[294,6742,6743,6745,6747,6749,6751,6753],{"class":296,"line":340},[294,6744,2112],{"class":1376},[294,6746,2092],{"class":1195},[294,6748,2117],{"class":315},[294,6750,2120],{"class":1195},[294,6752,2123],{"class":315},[294,6754,1208],{"class":311},[294,6756,6757,6759,6761,6763],{"class":296,"line":351},[294,6758,2130],{"class":1376},[294,6760,2092],{"class":1195},[294,6762,2135],{"class":315},[294,6764,1208],{"class":311},[294,6766,6767,6769,6771,6773],{"class":296,"line":362},[294,6768,2142],{"class":1376},[294,6770,2092],{"class":1195},[294,6772,2147],{"class":315},[294,6774,1208],{"class":311},[294,6776,6777],{"class":296,"line":369},[294,6778,2154],{"class":311},[294,6780,6781],{"class":296,"line":377},[294,6782,2159],{"class":311},[294,6784,6785],{"class":296,"line":385},[294,6786,366],{"emptyLinePlaceholder":365},[294,6788,6789],{"class":296,"line":393},[294,6790,2168],{"class":300},[19,6792,2171],{},[79,6794,2175],{"id":2174},[19,6796,2178,6797,2183],{},[2180,6798,2182],{},[79,6800,2187],{"id":2186},[19,6802,2190,6803,2194],{},[291,6804,2193],{},[284,6806,6807],{"className":2197,"code":2198,"language":1875,"meta":289,"style":289},[291,6808,6809,6813,6819,6829,6839,6845,6855,6861,6867,6873,6877,6881,6885,6889],{"__ignoreMap":289},[294,6810,6811],{"class":296,"line":297},[294,6812,2205],{"class":311},[294,6814,6815,6817],{"class":296,"line":304},[294,6816,2210],{"class":315},[294,6818,2213],{"class":311},[294,6820,6821,6823,6825,6827],{"class":296,"line":319},[294,6822,2218],{"class":315},[294,6824,312],{"class":311},[294,6826,2223],{"class":336},[294,6828,1243],{"class":311},[294,6830,6831,6833,6835,6837],{"class":296,"line":328},[294,6832,2230],{"class":315},[294,6834,312],{"class":311},[294,6836,2235],{"class":336},[294,6838,1243],{"class":311},[294,6840,6841,6843],{"class":296,"line":340},[294,6842,2242],{"class":315},[294,6844,2213],{"class":311},[294,6846,6847,6849,6851,6853],{"class":296,"line":351},[294,6848,2249],{"class":315},[294,6850,312],{"class":311},[294,6852,2254],{"class":336},[294,6854,1243],{"class":311},[294,6856,6857,6859],{"class":296,"line":362},[294,6858,2261],{"class":315},[294,6860,2264],{"class":311},[294,6862,6863,6865],{"class":296,"line":369},[294,6864,2269],{"class":336},[294,6866,1243],{"class":311},[294,6868,6869,6871],{"class":296,"line":377},[294,6870,2276],{"class":336},[294,6872,1243],{"class":311},[294,6874,6875],{"class":296,"line":385},[294,6876,2283],{"class":336},[294,6878,6879],{"class":296,"line":393},[294,6880,2288],{"class":311},[294,6882,6883],{"class":296,"line":404},[294,6884,2293],{"class":311},[294,6886,6887],{"class":296,"line":415},[294,6888,2298],{"class":311},[294,6890,6891],{"class":296,"line":423},[294,6892,2159],{"class":311},[19,6894,2305],{},[14,6896,2309],{"id":2308},[19,6898,2312],{},[47,6900,6901,6905,6909,6913,6917],{},[50,6902,6903,2320],{},[23,6904,2319],{},[50,6906,6907,2326],{},[23,6908,2325],{},[50,6910,6911,2332],{},[23,6912,2331],{},[50,6914,6915,2338],{},[23,6916,2337],{},[50,6918,6919,2344],{},[23,6920,2343],{},[19,6922,2347],{},[19,6924,2350,6925,2355],{},[230,6926,2354],{"href":2353},[2357,6928],{},[19,6930,6931],{},[2180,6932,2363,6933,2368],{},[230,6934,2367],{"href":2366},[2370,6936,2372],{},{"title":289,"searchDepth":304,"depth":304,"links":6938},[6939,6940,6941,6946,6952,6959,6962,6969],{"id":16,"depth":304,"text":17},{"id":38,"depth":304,"text":39},{"id":73,"depth":304,"text":74,"children":6942},[6943,6944,6945],{"id":81,"depth":319,"text":82},{"id":97,"depth":319,"text":98},{"id":111,"depth":319,"text":112},{"id":214,"depth":304,"text":215,"children":6947},[6948,6949,6950,6951],{"id":221,"depth":319,"text":222},{"id":237,"depth":319,"text":238},{"id":244,"depth":319,"text":245},{"id":264,"depth":319,"text":265},{"id":271,"depth":304,"text":272,"children":6953},[6954,6955,6956,6957,6958],{"id":278,"depth":319,"text":279},{"id":1091,"depth":319,"text":1092},{"id":1174,"depth":319,"text":1175},{"id":1672,"depth":319,"text":1673},{"id":1727,"depth":319,"text":1728},{"id":1957,"depth":304,"text":1958,"children":6960},[6961],{"id":1964,"depth":319,"text":1965},{"id":2020,"depth":304,"text":2021,"children":6963},[6964,6965,6966,6967,6968],{"id":2027,"depth":319,"text":2028},{"id":2034,"depth":319,"text":2035},{"id":2053,"depth":319,"text":2054},{"id":2174,"depth":319,"text":2175},{"id":2186,"depth":319,"text":2187},{"id":2308,"depth":304,"text":2309},{},{"title":6,"description":2409},[2418,141,2419,2420],{"id":2423,"title":2424,"author":6974,"body":6975,"category":3613,"coverImage":2407,"date":3614,"description":3615,"extension":2410,"featured":365,"meta":7893,"navigation":365,"path":3617,"readingTime":3618,"seo":7894,"stem":3620,"tags":7895,"__hash__":3625},{"name":2426,"role":2427},{"type":11,"value":6976,"toc":7867},[6977,6979,6983,6985,6989,6991,6993,6995,6997,6999,7001,7003,7005,7007,7009,7011,7013,7031,7299,7303,7305,7307,7309,7311,7313,7315,7317,7585,7587,7589,7591,7641,7643,7647,7649,7651,7653,7655,7657,7661,7663,7665,7667,7669,7687,7689,7691,7693,7707,7709,7711,7713,7715,7725,7727,7729,7731,7753,7755,7757,7759,7821,7825,7831,7833,7835,7855,7857,7859,7865],[14,6978,2433],{"id":2432},[19,6980,2436,6981,2439],{},[23,6982,252],{},[19,6984,2442],{},[31,6986,6987],{},[19,6988,2447],{},[14,6990,2451],{"id":2450},[19,6992,2454],{},[79,6994,2458],{"id":2457},[19,6996,2461],{},[79,6998,2465],{"id":2464},[19,7000,2468],{},[79,7002,2472],{"id":2471},[19,7004,2475],{},[19,7006,2478],{},[79,7008,2482],{"id":2481},[19,7010,2485],{},[19,7012,2488],{},[47,7014,7015,7019,7023,7027],{},[50,7016,7017,2496],{},[23,7018,2495],{},[50,7020,7021,2502],{},[23,7022,2501],{},[50,7024,7025,2508],{},[23,7026,2507],{},[50,7028,7029,2514],{},[23,7030,2513],{},[284,7032,7033],{"className":1181,"code":2517,"language":1183,"meta":289,"style":289},[291,7034,7035,7039,7047,7057,7067,7077,7095,7099,7103,7113,7123,7133,7147,7161,7175,7179,7195,7207,7211,7215,7223,7227,7231,7237,7259,7275,7279,7283,7287,7291,7295],{"__ignoreMap":289},[294,7036,7037],{"class":296,"line":297},[294,7038,2524],{"class":300},[294,7040,7041,7043,7045],{"class":296,"line":304},[294,7042,2072],{"class":1195},[294,7044,2531],{"class":1112},[294,7046,1282],{"class":311},[294,7048,7049,7051,7053,7055],{"class":296,"line":319},[294,7050,2538],{"class":1376},[294,7052,2092],{"class":1195},[294,7054,2117],{"class":315},[294,7056,1208],{"class":311},[294,7058,7059,7061,7063,7065],{"class":296,"line":328},[294,7060,2549],{"class":1376},[294,7062,2092],{"class":1195},[294,7064,2117],{"class":315},[294,7066,1208],{"class":311},[294,7068,7069,7071,7073,7075],{"class":296,"line":340},[294,7070,2560],{"class":1376},[294,7072,2092],{"class":1195},[294,7074,2147],{"class":315},[294,7076,1208],{"class":311},[294,7078,7079,7081,7083,7085,7087,7089,7091,7093],{"class":296,"line":351},[294,7080,2571],{"class":1376},[294,7082,2092],{"class":1195},[294,7084,2576],{"class":1112},[294,7086,2078],{"class":311},[294,7088,2581],{"class":315},[294,7090,1295],{"class":311},[294,7092,2586],{"class":315},[294,7094,2589],{"class":311},[294,7096,7097],{"class":296,"line":362},[294,7098,2159],{"class":311},[294,7100,7101],{"class":296,"line":369},[294,7102,366],{"emptyLinePlaceholder":365},[294,7104,7105,7107,7109,7111],{"class":296,"line":377},[294,7106,1298],{"class":1195},[294,7108,2604],{"class":1195},[294,7110,2607],{"class":1112},[294,7112,2610],{"class":311},[294,7114,7115,7117,7119,7121],{"class":296,"line":385},[294,7116,2615],{"class":1376},[294,7118,2092],{"class":1195},[294,7120,2117],{"class":315},[294,7122,1243],{"class":311},[294,7124,7125,7127,7129,7131],{"class":296,"line":393},[294,7126,2626],{"class":1376},[294,7128,2092],{"class":1195},[294,7130,2117],{"class":315},[294,7132,1243],{"class":311},[294,7134,7135,7137,7139,7141,7143,7145],{"class":296,"line":404},[294,7136,2637],{"class":1376},[294,7138,2092],{"class":1195},[294,7140,2147],{"class":315},[294,7142,1223],{"class":1195},[294,7144,2646],{"class":315},[294,7146,1243],{"class":311},[294,7148,7149,7151,7153,7155,7157,7159],{"class":296,"line":415},[294,7150,2653],{"class":311},[294,7152,2092],{"class":1195},[294,7154,2658],{"class":1112},[294,7156,2078],{"class":311},[294,7158,2663],{"class":1112},[294,7160,2666],{"class":311},[294,7162,7163,7165,7167,7169,7171,7173],{"class":296,"line":423},[294,7164,2671],{"class":1195},[294,7166,2674],{"class":315},[294,7168,1223],{"class":1195},[294,7170,1590],{"class":1195},[294,7172,2681],{"class":1112},[294,7174,2684],{"class":311},[294,7176,7177],{"class":296,"line":432},[294,7178,366],{"emptyLinePlaceholder":365},[294,7180,7181,7183,7185,7187,7189,7191,7193],{"class":296,"line":440},[294,7182,2671],{"class":1195},[294,7184,2695],{"class":315},[294,7186,1223],{"class":1195},[294,7188,1590],{"class":1195},[294,7190,2702],{"class":311},[294,7192,2705],{"class":1112},[294,7194,1232],{"class":311},[294,7196,7197,7199,7201,7203,7205],{"class":296,"line":451},[294,7198,2712],{"class":311},[294,7200,2715],{"class":336},[294,7202,2718],{"class":311},[294,7204,2721],{"class":336},[294,7206,1243],{"class":311},[294,7208,7209],{"class":296,"line":459},[294,7210,2728],{"class":311},[294,7212,7213],{"class":296,"line":467},[294,7214,2733],{"class":311},[294,7216,7217,7219,7221],{"class":296,"line":475},[294,7218,2738],{"class":311},[294,7220,2741],{"class":315},[294,7222,2744],{"class":311},[294,7224,7225],{"class":296,"line":486},[294,7226,1662],{"class":311},[294,7228,7229],{"class":296,"line":494},[294,7230,366],{"emptyLinePlaceholder":365},[294,7232,7233,7235],{"class":296,"line":502},[294,7234,2757],{"class":1195},[294,7236,2760],{"class":311},[294,7238,7239,7241,7243,7245,7247,7249,7251,7253,7255,7257],{"class":296,"line":513},[294,7240,2765],{"class":311},[294,7242,2768],{"class":1112},[294,7244,2771],{"class":311},[294,7246,2774],{"class":1376},[294,7248,1380],{"class":311},[294,7250,1279],{"class":1195},[294,7252,2781],{"class":311},[294,7254,2784],{"class":1195},[294,7256,2787],{"class":315},[294,7258,1339],{"class":311},[294,7260,7261,7263,7265,7267,7269,7271,7273],{"class":296,"line":521},[294,7262,2765],{"class":311},[294,7264,2796],{"class":1112},[294,7266,2771],{"class":311},[294,7268,2774],{"class":1376},[294,7270,1380],{"class":311},[294,7272,1279],{"class":1195},[294,7274,2807],{"class":311},[294,7276,7277],{"class":296,"line":529},[294,7278,2812],{"class":311},[294,7280,7281],{"class":296,"line":537},[294,7282,2817],{"class":311},[294,7284,7285],{"class":296,"line":548},[294,7286,2822],{"class":311},[294,7288,7289],{"class":296,"line":556},[294,7290,2827],{"class":311},[294,7292,7293],{"class":296,"line":566},[294,7294,2832],{"class":311},[294,7296,7297],{"class":296,"line":573},[294,7298,2159],{"class":311},[1162,7300,7301],{"type":322},[19,7302,2841],{},[79,7304,2845],{"id":2844},[19,7306,2848],{},[19,7308,2851],{},[14,7310,2855],{"id":2854},[19,7312,2858],{},[79,7314,2862],{"id":2861},[19,7316,2865],{},[284,7318,7319],{"className":1181,"code":2868,"language":1183,"meta":289,"style":289},[291,7320,7321,7325,7335,7343,7347,7353,7357,7365,7369,7373,7381,7389,7409,7413,7417,7425,7433,7441,7445,7449,7457,7473,7481,7485,7489,7497,7505,7509,7513,7521,7529,7533,7537,7545,7553,7557,7561,7577,7581],{"__ignoreMap":289},[294,7322,7323],{"class":296,"line":297},[294,7324,2875],{"class":300},[294,7326,7327,7329,7331,7333],{"class":296,"line":304},[294,7328,1217],{"class":1195},[294,7330,2882],{"class":315},[294,7332,1223],{"class":1195},[294,7334,1282],{"class":311},[294,7336,7337,7339,7341],{"class":296,"line":319},[294,7338,2891],{"class":311},[294,7340,2894],{"class":336},[294,7342,1243],{"class":311},[294,7344,7345],{"class":296,"line":328},[294,7346,2901],{"class":311},[294,7348,7349,7351],{"class":296,"line":340},[294,7350,2906],{"class":336},[294,7352,1243],{"class":311},[294,7354,7355],{"class":296,"line":351},[294,7356,2913],{"class":311},[294,7358,7359,7361,7363],{"class":296,"line":362},[294,7360,2918],{"class":311},[294,7362,2921],{"class":336},[294,7364,1243],{"class":311},[294,7366,7367],{"class":296,"line":369},[294,7368,2928],{"class":311},[294,7370,7371],{"class":296,"line":377},[294,7372,2933],{"class":311},[294,7374,7375,7377,7379],{"class":296,"line":385},[294,7376,2938],{"class":311},[294,7378,2941],{"class":336},[294,7380,1243],{"class":311},[294,7382,7383,7385,7387],{"class":296,"line":393},[294,7384,2948],{"class":311},[294,7386,2951],{"class":336},[294,7388,1243],{"class":311},[294,7390,7391,7393,7395,7397,7399,7401,7403,7405,7407],{"class":296,"line":404},[294,7392,2958],{"class":311},[294,7394,1428],{"class":336},[294,7396,1295],{"class":311},[294,7398,2965],{"class":336},[294,7400,1295],{"class":311},[294,7402,2970],{"class":336},[294,7404,1295],{"class":311},[294,7406,2975],{"class":336},[294,7408,2978],{"class":311},[294,7410,7411],{"class":296,"line":415},[294,7412,2983],{"class":311},[294,7414,7415],{"class":296,"line":423},[294,7416,2988],{"class":311},[294,7418,7419,7421,7423],{"class":296,"line":432},[294,7420,2938],{"class":311},[294,7422,2941],{"class":336},[294,7424,1243],{"class":311},[294,7426,7427,7429,7431],{"class":296,"line":440},[294,7428,3001],{"class":311},[294,7430,3004],{"class":336},[294,7432,1243],{"class":311},[294,7434,7435,7437,7439],{"class":296,"line":451},[294,7436,2948],{"class":311},[294,7438,3013],{"class":336},[294,7440,1243],{"class":311},[294,7442,7443],{"class":296,"line":459},[294,7444,2983],{"class":311},[294,7446,7447],{"class":296,"line":467},[294,7448,3024],{"class":311},[294,7450,7451,7453,7455],{"class":296,"line":475},[294,7452,2938],{"class":311},[294,7454,2941],{"class":336},[294,7456,1243],{"class":311},[294,7458,7459,7461,7463,7465,7467,7469,7471],{"class":296,"line":486},[294,7460,2958],{"class":311},[294,7462,3039],{"class":336},[294,7464,1295],{"class":311},[294,7466,3044],{"class":336},[294,7468,1295],{"class":311},[294,7470,3049],{"class":336},[294,7472,2978],{"class":311},[294,7474,7475,7477,7479],{"class":296,"line":494},[294,7476,2948],{"class":311},[294,7478,3058],{"class":336},[294,7480,1243],{"class":311},[294,7482,7483],{"class":296,"line":502},[294,7484,2983],{"class":311},[294,7486,7487],{"class":296,"line":513},[294,7488,3069],{"class":311},[294,7490,7491,7493,7495],{"class":296,"line":521},[294,7492,2938],{"class":311},[294,7494,2941],{"class":336},[294,7496,1243],{"class":311},[294,7498,7499,7501,7503],{"class":296,"line":529},[294,7500,2948],{"class":311},[294,7502,3084],{"class":336},[294,7504,1243],{"class":311},[294,7506,7507],{"class":296,"line":537},[294,7508,2983],{"class":311},[294,7510,7511],{"class":296,"line":548},[294,7512,3095],{"class":311},[294,7514,7515,7517,7519],{"class":296,"line":556},[294,7516,2938],{"class":311},[294,7518,2941],{"class":336},[294,7520,1243],{"class":311},[294,7522,7523,7525,7527],{"class":296,"line":566},[294,7524,2948],{"class":311},[294,7526,3110],{"class":336},[294,7528,1243],{"class":311},[294,7530,7531],{"class":296,"line":573},[294,7532,2983],{"class":311},[294,7534,7535],{"class":296,"line":580},[294,7536,3121],{"class":311},[294,7538,7539,7541,7543],{"class":296,"line":587},[294,7540,2938],{"class":311},[294,7542,2941],{"class":336},[294,7544,1243],{"class":311},[294,7546,7547,7549,7551],{"class":296,"line":597},[294,7548,2948],{"class":311},[294,7550,3136],{"class":336},[294,7552,1243],{"class":311},[294,7554,7555],{"class":296,"line":605},[294,7556,2983],{"class":311},[294,7558,7559],{"class":296,"line":615},[294,7560,3147],{"class":311},[294,7562,7563,7565,7567,7569,7571,7573,7575],{"class":296,"line":622},[294,7564,3152],{"class":311},[294,7566,3155],{"class":336},[294,7568,1295],{"class":311},[294,7570,3160],{"class":336},[294,7572,1295],{"class":311},[294,7574,3165],{"class":336},[294,7576,2978],{"class":311},[294,7578,7579],{"class":296,"line":629},[294,7580,1922],{"class":311},[294,7582,7583],{"class":296,"line":636},[294,7584,3176],{"class":311},[79,7586,3180],{"id":3179},[19,7588,3183],{},[19,7590,3186],{},[47,7592,7593,7597,7603,7607,7611,7615,7619,7623,7627,7631,7637],{},[50,7594,7595,3194],{},[23,7596,3193],{},[50,7598,7599,3200,7601],{},[23,7600,3199],{},[291,7602,3203],{},[50,7604,7605,3209],{},[23,7606,3208],{},[50,7608,7609,3214],{},[23,7610,3199],{},[50,7612,7613,3219],{},[23,7614,3193],{},[50,7616,7617,3224],{},[23,7618,3199],{},[50,7620,7621,3229],{},[23,7622,3193],{},[50,7624,7625,3234],{},[23,7626,3199],{},[50,7628,7629,3239],{},[23,7630,3193],{},[50,7632,7633,3200,7635],{},[23,7634,3199],{},[291,7636,3246],{},[50,7638,7639,3251],{},[23,7640,3199],{},[19,7642,3254],{},[1162,7644,7645],{"type":1164},[19,7646,3259],{},[14,7648,3263],{"id":3262},[19,7650,3266],{},[79,7652,3270],{"id":3269},[19,7654,3273],{},[79,7656,3277],{"id":3276},[19,7658,3280,7659,3284],{},[230,7660,3283],{"href":2353},[14,7662,3288],{"id":3287},[19,7664,3291],{},[79,7666,3295],{"id":3294},[19,7668,3298],{},[1711,7670,7671,7675,7679,7683],{},[50,7672,7673,3306],{},[23,7674,3305],{},[50,7676,7677,3312],{},[23,7678,3311],{},[50,7680,7681,3318],{},[23,7682,3317],{},[50,7684,7685,3324],{},[23,7686,3323],{},[79,7688,3328],{"id":3327},[19,7690,3331],{},[19,7692,3334],{},[47,7694,7695,7699,7703],{},[50,7696,7697,3342],{},[23,7698,3341],{},[50,7700,7701,3348],{},[23,7702,3347],{},[50,7704,7705,3354],{},[23,7706,3353],{},[19,7708,3357],{},[79,7710,3361],{"id":3360},[19,7712,3364],{},[19,7714,3367],{},[1711,7716,7717,7719,7721,7723],{},[50,7718,3372],{},[50,7720,3375],{},[50,7722,3378],{},[50,7724,3381],{},[19,7726,3384],{},[79,7728,3388],{"id":3387},[19,7730,3391],{},[1711,7732,7733,7737,7741,7745,7749],{},[50,7734,7735,3399],{},[23,7736,3398],{},[50,7738,7739,3405],{},[23,7740,3404],{},[50,7742,7743,3411],{},[23,7744,3410],{},[50,7746,7747,3417],{},[23,7748,3416],{},[50,7750,7751,3423],{},[23,7752,3422],{},[19,7754,3426],{},[14,7756,3430],{"id":3429},[19,7758,3433],{},[124,7760,7761,7771],{},[127,7762,7763],{},[130,7764,7765,7767,7769],{},[133,7766,3442],{},[133,7768,3445],{},[133,7770,3448],{},[143,7772,7773,7781,7789,7797,7805,7813],{},[130,7774,7775,7777,7779],{},[148,7776,3455],{},[148,7778,3458],{},[148,7780,3461],{},[130,7782,7783,7785,7787],{},[148,7784,3466],{},[148,7786,3469],{},[148,7788,3472],{},[130,7790,7791,7793,7795],{},[148,7792,3477],{},[148,7794,3480],{},[148,7796,3483],{},[130,7798,7799,7801,7803],{},[148,7800,3488],{},[148,7802,3491],{},[148,7804,3494],{},[130,7806,7807,7809,7811],{},[148,7808,3499],{},[148,7810,3502],{},[148,7812,3505],{},[130,7814,7815,7817,7819],{},[148,7816,3510],{},[148,7818,3513],{},[148,7820,3516],{},[19,7822,3519,7823,3523],{},[230,7824,3522],{"href":251},[1162,7826,7827],{"type":322},[19,7828,3528,7829,3532],{},[2180,7830,3531],{},[14,7832,3536],{"id":3535},[19,7834,3539],{},[1711,7836,7837,7841,7845,7851],{},[50,7838,7839,3547],{},[23,7840,3546],{},[50,7842,7843,3553],{},[23,7844,3552],{},[50,7846,7847,3563],{},[23,7848,3558,7849],{},[230,7850,3562],{"href":3561},[50,7852,7853,3569],{},[23,7854,3568],{},[19,7856,3572],{},[2357,7858],{},[19,7860,7861],{},[2180,7862,3579,7863,3583],{},[230,7864,3582],{"href":2366},[2370,7866,3586],{},{"title":289,"searchDepth":304,"depth":304,"links":7868},[7869,7870,7877,7881,7885,7891,7892],{"id":2432,"depth":304,"text":2433},{"id":2450,"depth":304,"text":2451,"children":7871},[7872,7873,7874,7875,7876],{"id":2457,"depth":319,"text":2458},{"id":2464,"depth":319,"text":2465},{"id":2471,"depth":319,"text":2472},{"id":2481,"depth":319,"text":2482},{"id":2844,"depth":319,"text":2845},{"id":2854,"depth":304,"text":2855,"children":7878},[7879,7880],{"id":2861,"depth":319,"text":2862},{"id":3179,"depth":319,"text":3180},{"id":3262,"depth":304,"text":3263,"children":7882},[7883,7884],{"id":3269,"depth":319,"text":3270},{"id":3276,"depth":319,"text":3277},{"id":3287,"depth":304,"text":3288,"children":7886},[7887,7888,7889,7890],{"id":3294,"depth":319,"text":3295},{"id":3327,"depth":319,"text":3328},{"id":3360,"depth":319,"text":3361},{"id":3387,"depth":319,"text":3388},{"id":3429,"depth":304,"text":3430},{"id":3535,"depth":304,"text":3536},{},{"title":2424,"description":3615},[252,3622,3623,3624],{"id":7897,"title":7898,"author":7899,"body":7902,"category":5168,"coverImage":2407,"date":9062,"description":9063,"extension":2410,"featured":2411,"meta":9064,"navigation":365,"path":9065,"readingTime":9066,"seo":9067,"stem":9068,"tags":9069,"__hash__":9073},"blog/blog/cloud-native-architecture.md","Cloud-Native Architecture: Building for Global Scale",{"name":7900,"role":7901},"Kavinda Silva","Principal Architect",{"type":11,"value":7903,"toc":9051},[7904,7908,7911,7915,7919,7922,8299,8609,8613,8616,8619,8638,8643,8647,8650,8670,8675,8679,8682,8926,8932,8936,8939,8942,8968,8972,8975,9035,9038,9040,9048],[14,7905,7907],{"id":7906},"beyond-containers-true-cloud-native-thinking","Beyond Containers: True Cloud-Native Thinking",[19,7909,7910],{},"Cloud-native isn't just about running containers in Kubernetes. It's a philosophy — a way of designing systems that fully exploits the cloud's elastic, distributed nature. After architecting platforms that serve millions of users across four continents, we've distilled our approach into core principles.",[14,7912,7914],{"id":7913},"the-three-pillars-of-cloud-native-architecture","The Three Pillars of Cloud-Native Architecture",[79,7916,7918],{"id":7917},"_1-resilience-as-a-first-class-concern","1. Resilience as a First-Class Concern",[19,7920,7921],{},"Every service must be designed to fail gracefully. This isn't pessimism — it's engineering reality. In a distributed system with hundreds of services, something is always failing.",[284,7923,7927],{"className":7924,"code":7925,"language":7926,"meta":289,"style":289},"language-go shiki shiki-themes github-light github-dark","// Circuit breaker pattern in Go\ntype CircuitBreaker struct {\n    maxFailures   int\n    resetTimeout  time.Duration\n    failures      int\n    lastFailure   time.Time\n    state         State\n    mu            sync.Mutex\n}\n\nfunc (cb *CircuitBreaker) Execute(fn func() error) error {\n    cb.mu.Lock()\n    if cb.state == Open {\n        if time.Since(cb.lastFailure) > cb.resetTimeout {\n            cb.state = HalfOpen\n        } else {\n            cb.mu.Unlock()\n            return ErrCircuitOpen\n        }\n    }\n    cb.mu.Unlock()\n\n    err := fn()\n    cb.mu.Lock()\n    defer cb.mu.Unlock()\n\n    if err != nil {\n        cb.failures++\n        cb.lastFailure = time.Now()\n        if cb.failures >= cb.maxFailures {\n            cb.state = Open\n        }\n        return err\n    }\n\n    cb.failures = 0\n    cb.state = Closed\n    return nil\n}\n","go",[291,7928,7929,7934,7946,7954,7967,7974,7986,7994,8007,8011,8015,8054,8064,8077,8096,8106,8115,8125,8133,8138,8142,8150,8154,8166,8174,8186,8190,8205,8213,8227,8239,8248,8252,8259,8263,8267,8277,8287,8295],{"__ignoreMap":289},[294,7930,7931],{"class":296,"line":297},[294,7932,7933],{"class":300},"// Circuit breaker pattern in Go\n",[294,7935,7936,7939,7941,7944],{"class":296,"line":304},[294,7937,7938],{"class":1195},"type",[294,7940,4225],{"class":1112},[294,7942,7943],{"class":1195}," struct",[294,7945,1282],{"class":311},[294,7947,7948,7951],{"class":296,"line":319},[294,7949,7950],{"class":311},"    maxFailures   ",[294,7952,7953],{"class":1195},"int\n",[294,7955,7956,7959,7962,7964],{"class":296,"line":328},[294,7957,7958],{"class":311},"    resetTimeout  ",[294,7960,7961],{"class":1112},"time",[294,7963,4530],{"class":311},[294,7965,7966],{"class":1112},"Duration\n",[294,7968,7969,7972],{"class":296,"line":340},[294,7970,7971],{"class":311},"    failures      ",[294,7973,7953],{"class":1195},[294,7975,7976,7979,7981,7983],{"class":296,"line":351},[294,7977,7978],{"class":311},"    lastFailure   ",[294,7980,7961],{"class":1112},[294,7982,4530],{"class":311},[294,7984,7985],{"class":1112},"Time\n",[294,7987,7988,7991],{"class":296,"line":362},[294,7989,7990],{"class":311},"    state         ",[294,7992,7993],{"class":1112},"State\n",[294,7995,7996,7999,8002,8004],{"class":296,"line":369},[294,7997,7998],{"class":311},"    mu            ",[294,8000,8001],{"class":1112},"sync",[294,8003,4530],{"class":311},[294,8005,8006],{"class":1112},"Mutex\n",[294,8008,8009],{"class":296,"line":377},[294,8010,2159],{"class":311},[294,8012,8013],{"class":296,"line":385},[294,8014,366],{"emptyLinePlaceholder":365},[294,8016,8017,8020,8022,8025,8028,8031,8033,8036,8038,8040,8043,8045,8048,8050,8052],{"class":296,"line":393},[294,8018,8019],{"class":1195},"func",[294,8021,1568],{"class":311},[294,8023,8024],{"class":1376},"cb ",[294,8026,8027],{"class":1195},"*",[294,8029,8030],{"class":1112},"CircuitBreaker",[294,8032,1380],{"class":311},[294,8034,8035],{"class":1112},"Execute",[294,8037,1270],{"class":311},[294,8039,4357],{"class":1376},[294,8041,8042],{"class":1195}," func",[294,8044,4430],{"class":311},[294,8046,8047],{"class":1195},"error",[294,8049,1380],{"class":311},[294,8051,8047],{"class":1195},[294,8053,1282],{"class":311},[294,8055,8056,8059,8062],{"class":296,"line":404},[294,8057,8058],{"class":311},"    cb.mu.",[294,8060,8061],{"class":1112},"Lock",[294,8063,1324],{"class":311},[294,8065,8066,8068,8071,8074],{"class":296,"line":415},[294,8067,4400],{"class":1195},[294,8069,8070],{"class":311}," cb.state ",[294,8072,8073],{"class":1195},"==",[294,8075,8076],{"class":311}," Open {\n",[294,8078,8079,8082,8085,8088,8091,8093],{"class":296,"line":423},[294,8080,8081],{"class":1195},"        if",[294,8083,8084],{"class":311}," time.",[294,8086,8087],{"class":1112},"Since",[294,8089,8090],{"class":311},"(cb.lastFailure) ",[294,8092,2784],{"class":1195},[294,8094,8095],{"class":311}," cb.resetTimeout {\n",[294,8097,8098,8101,8103],{"class":296,"line":432},[294,8099,8100],{"class":311},"            cb.state ",[294,8102,4456],{"class":1195},[294,8104,8105],{"class":311}," HalfOpen\n",[294,8107,8108,8111,8113],{"class":296,"line":440},[294,8109,8110],{"class":311},"        } ",[294,8112,4468],{"class":1195},[294,8114,1282],{"class":311},[294,8116,8117,8120,8123],{"class":296,"line":451},[294,8118,8119],{"class":311},"            cb.mu.",[294,8121,8122],{"class":1112},"Unlock",[294,8124,1324],{"class":311},[294,8126,8127,8130],{"class":296,"line":459},[294,8128,8129],{"class":1195},"            return",[294,8131,8132],{"class":311}," ErrCircuitOpen\n",[294,8134,8135],{"class":296,"line":467},[294,8136,8137],{"class":311},"        }\n",[294,8139,8140],{"class":296,"line":475},[294,8141,2293],{"class":311},[294,8143,8144,8146,8148],{"class":296,"line":486},[294,8145,8058],{"class":311},[294,8147,8122],{"class":1112},[294,8149,1324],{"class":311},[294,8151,8152],{"class":296,"line":494},[294,8153,366],{"emptyLinePlaceholder":365},[294,8155,8156,8159,8162,8164],{"class":296,"line":502},[294,8157,8158],{"class":311},"    err ",[294,8160,8161],{"class":1195},":=",[294,8163,4519],{"class":1112},[294,8165,1324],{"class":311},[294,8167,8168,8170,8172],{"class":296,"line":513},[294,8169,8058],{"class":311},[294,8171,8061],{"class":1112},[294,8173,1324],{"class":311},[294,8175,8176,8179,8182,8184],{"class":296,"line":521},[294,8177,8178],{"class":1195},"    defer",[294,8180,8181],{"class":311}," cb.mu.",[294,8183,8122],{"class":1112},[294,8185,1324],{"class":311},[294,8187,8188],{"class":296,"line":529},[294,8189,366],{"emptyLinePlaceholder":365},[294,8191,8192,8194,8197,8200,8203],{"class":296,"line":537},[294,8193,4400],{"class":1195},[294,8195,8196],{"class":311}," err ",[294,8198,8199],{"class":1195},"!=",[294,8201,8202],{"class":315}," nil",[294,8204,1282],{"class":311},[294,8206,8207,8210],{"class":296,"line":548},[294,8208,8209],{"class":311},"        cb.failures",[294,8211,8212],{"class":1195},"++\n",[294,8214,8215,8218,8220,8222,8225],{"class":296,"line":556},[294,8216,8217],{"class":311},"        cb.lastFailure ",[294,8219,4456],{"class":1195},[294,8221,8084],{"class":311},[294,8223,8224],{"class":1112},"Now",[294,8226,1324],{"class":311},[294,8228,8229,8231,8234,8236],{"class":296,"line":566},[294,8230,8081],{"class":1195},[294,8232,8233],{"class":311}," cb.failures ",[294,8235,4678],{"class":1195},[294,8237,8238],{"class":311}," cb.maxFailures {\n",[294,8240,8241,8243,8245],{"class":296,"line":573},[294,8242,8100],{"class":311},[294,8244,4456],{"class":1195},[294,8246,8247],{"class":311}," Open\n",[294,8249,8250],{"class":296,"line":580},[294,8251,8137],{"class":311},[294,8253,8254,8256],{"class":296,"line":587},[294,8255,4475],{"class":1195},[294,8257,8258],{"class":311}," err\n",[294,8260,8261],{"class":296,"line":597},[294,8262,2293],{"class":311},[294,8264,8265],{"class":296,"line":605},[294,8266,366],{"emptyLinePlaceholder":365},[294,8268,8269,8272,8274],{"class":296,"line":615},[294,8270,8271],{"class":311},"    cb.failures ",[294,8273,4456],{"class":1195},[294,8275,8276],{"class":315}," 0\n",[294,8278,8279,8282,8284],{"class":296,"line":622},[294,8280,8281],{"class":311},"    cb.state ",[294,8283,4456],{"class":1195},[294,8285,8286],{"class":311}," Closed\n",[294,8288,8289,8292],{"class":296,"line":629},[294,8290,8291],{"class":1195},"    return",[294,8293,8294],{"class":315}," nil\n",[294,8296,8297],{"class":296,"line":636},[294,8298,2159],{"class":311},[284,8300,8302],{"className":286,"code":8301,"language":288,"meta":289,"style":289},"# Kubernetes deployment with resilience patterns\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: payment-service\nspec:\n  replicas: 3\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 1\n      maxSurge: 1\n  template:\n    spec:\n      containers:\n        - name: payment\n          image: cnex/payment:v2.4.1\n          resources:\n            requests:\n              memory: \"256Mi\"\n              cpu: \"250m\"\n            limits:\n              memory: \"512Mi\"\n              cpu: \"500m\"\n          livenessProbe:\n            httpGet:\n              path: /healthz\n              port: 8080\n            initialDelaySeconds: 15\n            periodSeconds: 10\n          readinessProbe:\n            httpGet:\n              path: /readyz\n              port: 8080\n            initialDelaySeconds: 5\n            periodSeconds: 5\n",[291,8303,8304,8309,8319,8329,8336,8346,8353,8363,8370,8380,8387,8397,8406,8413,8420,8427,8439,8449,8456,8463,8473,8483,8490,8499,8508,8515,8522,8532,8542,8552,8562,8569,8575,8584,8592,8601],{"__ignoreMap":289},[294,8305,8306],{"class":296,"line":297},[294,8307,8308],{"class":300},"# Kubernetes deployment with resilience patterns\n",[294,8310,8311,8314,8316],{"class":296,"line":304},[294,8312,8313],{"class":307},"apiVersion",[294,8315,312],{"class":311},[294,8317,8318],{"class":336},"apps/v1\n",[294,8320,8321,8324,8326],{"class":296,"line":319},[294,8322,8323],{"class":307},"kind",[294,8325,312],{"class":311},[294,8327,8328],{"class":336},"Deployment\n",[294,8330,8331,8334],{"class":296,"line":328},[294,8332,8333],{"class":307},"metadata",[294,8335,325],{"class":311},[294,8337,8338,8341,8343],{"class":296,"line":340},[294,8339,8340],{"class":307},"  name",[294,8342,312],{"class":311},[294,8344,8345],{"class":336},"payment-service\n",[294,8347,8348,8351],{"class":296,"line":351},[294,8349,8350],{"class":307},"spec",[294,8352,325],{"class":311},[294,8354,8355,8358,8360],{"class":296,"line":362},[294,8356,8357],{"class":307},"  replicas",[294,8359,312],{"class":311},[294,8361,8362],{"class":315},"3\n",[294,8364,8365,8368],{"class":296,"line":369},[294,8366,8367],{"class":307},"  strategy",[294,8369,325],{"class":311},[294,8371,8372,8375,8377],{"class":296,"line":377},[294,8373,8374],{"class":307},"    type",[294,8376,312],{"class":311},[294,8378,8379],{"class":336},"RollingUpdate\n",[294,8381,8382,8385],{"class":296,"line":385},[294,8383,8384],{"class":307},"    rollingUpdate",[294,8386,325],{"class":311},[294,8388,8389,8392,8394],{"class":296,"line":393},[294,8390,8391],{"class":307},"      maxUnavailable",[294,8393,312],{"class":311},[294,8395,8396],{"class":315},"1\n",[294,8398,8399,8402,8404],{"class":296,"line":404},[294,8400,8401],{"class":307},"      maxSurge",[294,8403,312],{"class":311},[294,8405,8396],{"class":315},[294,8407,8408,8411],{"class":296,"line":415},[294,8409,8410],{"class":307},"  template",[294,8412,325],{"class":311},[294,8414,8415,8418],{"class":296,"line":423},[294,8416,8417],{"class":307},"    spec",[294,8419,325],{"class":311},[294,8421,8422,8425],{"class":296,"line":432},[294,8423,8424],{"class":307},"      containers",[294,8426,325],{"class":311},[294,8428,8429,8431,8434,8436],{"class":296,"line":440},[294,8430,426],{"class":311},[294,8432,8433],{"class":307},"name",[294,8435,312],{"class":311},[294,8437,8438],{"class":336},"payment\n",[294,8440,8441,8444,8446],{"class":296,"line":451},[294,8442,8443],{"class":307},"          image",[294,8445,312],{"class":311},[294,8447,8448],{"class":336},"cnex/payment:v2.4.1\n",[294,8450,8451,8454],{"class":296,"line":459},[294,8452,8453],{"class":307},"          resources",[294,8455,325],{"class":311},[294,8457,8458,8461],{"class":296,"line":467},[294,8459,8460],{"class":307},"            requests",[294,8462,325],{"class":311},[294,8464,8465,8468,8470],{"class":296,"line":475},[294,8466,8467],{"class":307},"              memory",[294,8469,312],{"class":311},[294,8471,8472],{"class":336},"\"256Mi\"\n",[294,8474,8475,8478,8480],{"class":296,"line":486},[294,8476,8477],{"class":307},"              cpu",[294,8479,312],{"class":311},[294,8481,8482],{"class":336},"\"250m\"\n",[294,8484,8485,8488],{"class":296,"line":494},[294,8486,8487],{"class":307},"            limits",[294,8489,325],{"class":311},[294,8491,8492,8494,8496],{"class":296,"line":502},[294,8493,8467],{"class":307},[294,8495,312],{"class":311},[294,8497,8498],{"class":336},"\"512Mi\"\n",[294,8500,8501,8503,8505],{"class":296,"line":513},[294,8502,8477],{"class":307},[294,8504,312],{"class":311},[294,8506,8507],{"class":336},"\"500m\"\n",[294,8509,8510,8513],{"class":296,"line":521},[294,8511,8512],{"class":307},"          livenessProbe",[294,8514,325],{"class":311},[294,8516,8517,8520],{"class":296,"line":529},[294,8518,8519],{"class":307},"            httpGet",[294,8521,325],{"class":311},[294,8523,8524,8527,8529],{"class":296,"line":537},[294,8525,8526],{"class":307},"              path",[294,8528,312],{"class":311},[294,8530,8531],{"class":336},"/healthz\n",[294,8533,8534,8537,8539],{"class":296,"line":548},[294,8535,8536],{"class":307},"              port",[294,8538,312],{"class":311},[294,8540,8541],{"class":315},"8080\n",[294,8543,8544,8547,8549],{"class":296,"line":556},[294,8545,8546],{"class":307},"            initialDelaySeconds",[294,8548,312],{"class":311},[294,8550,8551],{"class":315},"15\n",[294,8553,8554,8557,8559],{"class":296,"line":566},[294,8555,8556],{"class":307},"            periodSeconds",[294,8558,312],{"class":311},[294,8560,8561],{"class":315},"10\n",[294,8563,8564,8567],{"class":296,"line":573},[294,8565,8566],{"class":307},"          readinessProbe",[294,8568,325],{"class":311},[294,8570,8571,8573],{"class":296,"line":580},[294,8572,8519],{"class":307},[294,8574,325],{"class":311},[294,8576,8577,8579,8581],{"class":296,"line":587},[294,8578,8526],{"class":307},[294,8580,312],{"class":311},[294,8582,8583],{"class":336},"/readyz\n",[294,8585,8586,8588,8590],{"class":296,"line":597},[294,8587,8536],{"class":307},[294,8589,312],{"class":311},[294,8591,8541],{"class":315},[294,8593,8594,8596,8598],{"class":296,"line":605},[294,8595,8546],{"class":307},[294,8597,312],{"class":311},[294,8599,8600],{"class":315},"5\n",[294,8602,8603,8605,8607],{"class":296,"line":615},[294,8604,8556],{"class":307},[294,8606,312],{"class":311},[294,8608,8600],{"class":315},[79,8610,8612],{"id":8611},"_2-observability-over-monitoring","2. Observability Over Monitoring",[19,8614,8615],{},"Traditional monitoring asks \"Is it up?\" Observability asks \"Why is it behaving this way?\" The difference is critical at scale.",[19,8617,8618],{},"We instrument every service with three pillars of observability:",[1711,8620,8621,8627,8633],{},[50,8622,8623,8626],{},[23,8624,8625],{},"Structured logging"," with correlation IDs that trace requests across service boundaries",[50,8628,8629,8632],{},[23,8630,8631],{},"Distributed tracing"," via OpenTelemetry, giving us end-to-end request visibility",[50,8634,8635,8637],{},[23,8636,4780],{}," with dimensional tagging for flexible querying and alerting",[1162,8639,8640],{"type":322},[19,8641,8642],{},"A well-instrumented system should allow any engineer to diagnose a production issue within 5 minutes, without needing to be the service owner.",[79,8644,8646],{"id":8645},"_3-progressive-delivery","3. Progressive Delivery",[19,8648,8649],{},"Deploying to production should be boring. We achieve this through a layered deployment strategy:",[47,8651,8652,8658,8664],{},[50,8653,8654,8657],{},[23,8655,8656],{},"Canary releases"," — 5% of traffic to the new version, automated rollback on error spike",[50,8659,8660,8663],{},[23,8661,8662],{},"Feature flags"," — Decouple deployment from release, ship code dark",[50,8665,8666,8669],{},[23,8667,8668],{},"Blue-green environments"," — Zero-downtime database migrations and infrastructure changes",[31,8671,8672],{},[19,8673,8674],{},"We deploy to production an average of 47 times per day across our platform. Not because we're reckless — because our delivery pipeline makes it safe.",[14,8676,8678],{"id":8677},"infrastructure-as-code-the-complete-stack","Infrastructure as Code: The Complete Stack",[19,8680,8681],{},"Everything is code. Everything is version controlled. Everything is reviewable.",[284,8683,8685],{"className":1181,"code":8684,"language":1183,"meta":289,"style":289},"// Pulumi infrastructure definition (TypeScript)\nimport * as pulumi from '@pulumi/pulumi';\nimport * as aws from '@pulumi/aws';\nimport * as k8s from '@pulumi/kubernetes';\n\nconst vpc = new aws.ec2.Vpc('main', {\n  cidrBlock: '10.0.0.0/16',\n  enableDnsHostnames: true,\n  tags: { Environment: pulumi.getStack() },\n});\n\nconst cluster = new aws.eks.Cluster('platform', {\n  vpcConfig: {\n    subnetIds: subnets.map((s) => s.id),\n    securityGroupIds: [securityGroup.id],\n  },\n  version: '1.29',\n});\n\nconst namespace = new k8s.core.v1.Namespace('services', {\n  metadata: { name: 'services' },\n}, { provider: k8sProvider });\n",[291,8686,8687,8692,8711,8729,8747,8751,8776,8786,8795,8806,8810,8814,8838,8843,8862,8867,8871,8881,8885,8889,8913,8921],{"__ignoreMap":289},[294,8688,8689],{"class":296,"line":297},[294,8690,8691],{"class":300},"// Pulumi infrastructure definition (TypeScript)\n",[294,8693,8694,8696,8698,8701,8704,8706,8709],{"class":296,"line":304},[294,8695,1196],{"class":1195},[294,8697,1784],{"class":315},[294,8699,8700],{"class":1195}," as",[294,8702,8703],{"class":311}," pulumi ",[294,8705,1202],{"class":1195},[294,8707,8708],{"class":336}," '@pulumi/pulumi'",[294,8710,1208],{"class":311},[294,8712,8713,8715,8717,8719,8722,8724,8727],{"class":296,"line":319},[294,8714,1196],{"class":1195},[294,8716,1784],{"class":315},[294,8718,8700],{"class":1195},[294,8720,8721],{"class":311}," aws ",[294,8723,1202],{"class":1195},[294,8725,8726],{"class":336}," '@pulumi/aws'",[294,8728,1208],{"class":311},[294,8730,8731,8733,8735,8737,8740,8742,8745],{"class":296,"line":328},[294,8732,1196],{"class":1195},[294,8734,1784],{"class":315},[294,8736,8700],{"class":1195},[294,8738,8739],{"class":311}," k8s ",[294,8741,1202],{"class":1195},[294,8743,8744],{"class":336}," '@pulumi/kubernetes'",[294,8746,1208],{"class":311},[294,8748,8749],{"class":296,"line":340},[294,8750,366],{"emptyLinePlaceholder":365},[294,8752,8753,8755,8758,8760,8762,8765,8768,8770,8773],{"class":296,"line":351},[294,8754,1217],{"class":1195},[294,8756,8757],{"class":315}," vpc",[294,8759,1223],{"class":1195},[294,8761,1226],{"class":1195},[294,8763,8764],{"class":311}," aws.ec2.",[294,8766,8767],{"class":1112},"Vpc",[294,8769,1270],{"class":311},[294,8771,8772],{"class":336},"'main'",[294,8774,8775],{"class":311},", {\n",[294,8777,8778,8781,8784],{"class":296,"line":362},[294,8779,8780],{"class":311},"  cidrBlock: ",[294,8782,8783],{"class":336},"'10.0.0.0/16'",[294,8785,1243],{"class":311},[294,8787,8788,8791,8793],{"class":296,"line":369},[294,8789,8790],{"class":311},"  enableDnsHostnames: ",[294,8792,2741],{"class":315},[294,8794,1243],{"class":311},[294,8796,8797,8800,8803],{"class":296,"line":377},[294,8798,8799],{"class":311},"  tags: { Environment: pulumi.",[294,8801,8802],{"class":1112},"getStack",[294,8804,8805],{"class":311},"() },\n",[294,8807,8808],{"class":296,"line":385},[294,8809,1258],{"class":311},[294,8811,8812],{"class":296,"line":393},[294,8813,366],{"emptyLinePlaceholder":365},[294,8815,8816,8818,8821,8823,8825,8828,8831,8833,8836],{"class":296,"line":404},[294,8817,1217],{"class":1195},[294,8819,8820],{"class":315}," cluster",[294,8822,1223],{"class":1195},[294,8824,1226],{"class":1195},[294,8826,8827],{"class":311}," aws.eks.",[294,8829,8830],{"class":1112},"Cluster",[294,8832,1270],{"class":311},[294,8834,8835],{"class":336},"'platform'",[294,8837,8775],{"class":311},[294,8839,8840],{"class":296,"line":415},[294,8841,8842],{"class":311},"  vpcConfig: {\n",[294,8844,8845,8848,8850,8852,8855,8857,8859],{"class":296,"line":423},[294,8846,8847],{"class":311},"    subnetIds: subnets.",[294,8849,2796],{"class":1112},[294,8851,2771],{"class":311},[294,8853,8854],{"class":1376},"s",[294,8856,1380],{"class":311},[294,8858,1279],{"class":1195},[294,8860,8861],{"class":311}," s.id),\n",[294,8863,8864],{"class":296,"line":432},[294,8865,8866],{"class":311},"    securityGroupIds: [securityGroup.id],\n",[294,8868,8869],{"class":296,"line":440},[294,8870,1922],{"class":311},[294,8872,8873,8876,8879],{"class":296,"line":451},[294,8874,8875],{"class":311},"  version: ",[294,8877,8878],{"class":336},"'1.29'",[294,8880,1243],{"class":311},[294,8882,8883],{"class":296,"line":459},[294,8884,1258],{"class":311},[294,8886,8887],{"class":296,"line":467},[294,8888,366],{"emptyLinePlaceholder":365},[294,8890,8891,8893,8896,8898,8900,8903,8906,8908,8911],{"class":296,"line":475},[294,8892,1217],{"class":1195},[294,8894,8895],{"class":315}," namespace",[294,8897,1223],{"class":1195},[294,8899,1226],{"class":1195},[294,8901,8902],{"class":311}," k8s.core.v1.",[294,8904,8905],{"class":1112},"Namespace",[294,8907,1270],{"class":311},[294,8909,8910],{"class":336},"'services'",[294,8912,8775],{"class":311},[294,8914,8915,8917,8919],{"class":296,"line":486},[294,8916,3907],{"class":311},[294,8918,8910],{"class":336},[294,8920,2744],{"class":311},[294,8922,8923],{"class":296,"line":494},[294,8924,8925],{"class":311},"}, { provider: k8sProvider });\n",[1162,8927,8929],{"type":8928},"warning",[19,8930,8931],{},"Never store secrets in your IaC definitions. Use a dedicated secrets manager (AWS Secrets Manager, HashiCorp Vault) with dynamic secret rotation.",[14,8933,8935],{"id":8934},"the-cost-of-getting-it-wrong","The Cost of Getting It Wrong",[19,8937,8938],{},"We've seen enterprises spend millions on \"cloud migration\" that's really just lift-and-shift — running the same monolith on EC2 instead of bare metal. The result? Higher costs, same fragility, new complexity.",[19,8940,8941],{},"True cloud-native transformation requires:",[1711,8943,8944,8950,8956,8962],{},[50,8945,8946,8949],{},[23,8947,8948],{},"Decomposing the monolith"," along business domain boundaries (not technical layers)",[50,8951,8952,8955],{},[23,8953,8954],{},"Embracing eventual consistency"," where strong consistency isn't required",[50,8957,8958,8961],{},[23,8959,8960],{},"Investing in platform engineering"," so application teams can self-serve",[50,8963,8964,8967],{},[23,8965,8966],{},"Building a culture of ownership"," where teams own their services end-to-end",[14,8969,8971],{"id":8970},"real-world-results","Real-World Results",[19,8973,8974],{},"For a recent financial services client, our cloud-native replatforming delivered:",[124,8976,8977,8989],{},[127,8978,8979],{},[130,8980,8981,8983,8986],{},[133,8982,3442],{},[133,8984,8985],{},"Before",[133,8987,8988],{},"After",[143,8990,8991,9002,9013,9024],{},[130,8992,8993,8996,8999],{},[148,8994,8995],{},"Deploy frequency",[148,8997,8998],{},"Weekly",[148,9000,9001],{},"47x daily",[130,9003,9004,9007,9010],{},[148,9005,9006],{},"Lead time for changes",[148,9008,9009],{},"3 weeks",[148,9011,9012],{},"45 minutes",[130,9014,9015,9018,9021],{},[148,9016,9017],{},"Change failure rate",[148,9019,9020],{},"23%",[148,9022,9023],{},"1.8%",[130,9025,9026,9029,9032],{},[148,9027,9028],{},"Mean time to recovery",[148,9030,9031],{},"4 hours",[148,9033,9034],{},"8 minutes",[19,9036,9037],{},"These aren't theoretical improvements. They're the difference between a company that reacts to market changes and one that drives them.",[2357,9039],{},[19,9041,9042],{},[2180,9043,9044,9045,4530],{},"Ready to modernise your infrastructure? ",[230,9046,9047],{"href":2366},"Let's architect your cloud-native future",[2370,9049,9050],{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":289,"searchDepth":304,"depth":304,"links":9052},[9053,9054,9059,9060,9061],{"id":7906,"depth":304,"text":7907},{"id":7913,"depth":304,"text":7914,"children":9055},[9056,9057,9058],{"id":7917,"depth":319,"text":7918},{"id":8611,"depth":319,"text":8612},{"id":8645,"depth":319,"text":8646},{"id":8677,"depth":304,"text":8678},{"id":8934,"depth":304,"text":8935},{"id":8970,"depth":304,"text":8971},"2026-02-05","A deep dive into the architectural patterns and practices that enable enterprise applications to scale globally while maintaining reliability and performance.",{},"/blog/cloud-native-architecture","10 min read",{"title":7898,"description":9063},"blog/cloud-native-architecture",[9070,9071,2419,9072],"Cloud Native","Kubernetes","Architecture","Dai7RhZjlbZ0dr9DAwJlAIRurZr3eGCVoknlYA4NHXE",1784192087966]