[{"data":1,"prerenderedAt":8930},["ShallowReactive",2],{"blog-golang-grpc-microservices":3,"blog-related-golang-grpc-microservices":1843,"content-query-2PaIQfMWLq":7405},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"slug":10,"date":11,"readTime":12,"category":13,"image":14,"imageCaption":15,"author":16,"tags":25,"body":30,"_type":1837,"_id":1838,"_source":1839,"_file":1840,"_stem":1841,"_extension":1842},"/blog/golang-grpc-microservices","blog",false,"","Go + gRPC: Building Microservices That Handle Millions of Requests Efficiently","How to combine Go's concurrency model with gRPC's binary protocol for microservices that are fast, observable, and resilient—with practical patterns for service discovery, circuit breaking, and distributed tracing.","golang-grpc-microservices","2025-03-15","12 min","Backend","https://images.unsplash.com/photo-1461749280684-dccba630e2f6?w=1200&h=600&fit=crop&auto=format","High-performance backend code running Go microservices with gRPC communication",{"name":17,"role":18,"avatar":19,"bio":20,"social":21},"Tobias Lie-Atjam","Founder & Senior Software Engineer at MediaFront","https://images.unsplash.com/photo-1560250097-0b93528c311a?w=400&h=400&fit=crop&auto=format","Tobias is the founder of MediaFront. He specialises in cloud-native architecture, Rust, and .NET—helping businesses build high-performance systems that scale.",{"github":22,"twitter":23,"linkedin":24},"https://github.com/","https://twitter.com/","https://linkedin.com/",[26,27,28,29,13],"Go","gRPC","Microservices","Performance",{"type":31,"children":32,"toc":1828},"root",[33,42,57,62,68,80,348,369,375,1050,1063,1069,1074,1356,1362,1367,1513,1526,1532,1537,1729,1742,1748,1761,1807,1812,1817,1822],{"type":34,"tag":35,"props":36,"children":38},"element","h2",{"id":37},"why-go-and-grpc-belong-together",[39],{"type":40,"value":41},"text","Why Go and gRPC Belong Together",{"type":34,"tag":43,"props":44,"children":45},"p",{},[46,48,55],{"type":40,"value":47},"Go was built for network services. Its goroutine model handles 100,000+ concurrent connections on a single process while using a fraction of the memory a comparable Java or Node.js service would need. gRPC provides the communication layer: binary Protocol Buffer serialisation over HTTP/2, generating type-safe clients in any language from a single ",{"type":34,"tag":49,"props":50,"children":52},"code",{"className":51},[],[53],{"type":40,"value":54},".proto",{"type":40,"value":56}," file.",{"type":34,"tag":43,"props":58,"children":59},{},[60],{"type":40,"value":61},"Together, they address the two biggest costs in high-throughput microservices: CPU time serialising/deserialising data (gRPC's Protobuf is 3–5× more efficient than JSON), and the overhead of managing thousands of simultaneous connections (Go's runtime scheduler does this natively).",{"type":34,"tag":35,"props":63,"children":65},{"id":64},"defining-your-service-contract",[66],{"type":40,"value":67},"Defining Your Service Contract",{"type":34,"tag":43,"props":69,"children":70},{},[71,73,78],{"type":40,"value":72},"Everything in gRPC starts with a ",{"type":34,"tag":49,"props":74,"children":76},{"className":75},[],[77],{"type":40,"value":54},{"type":40,"value":79}," file. This is your API contract — auto-generate clients in Go, TypeScript, Python, or a dozen other languages from the same source of truth:",{"type":34,"tag":81,"props":82,"children":86},"pre",{"className":83,"code":84,"language":85,"meta":7,"style":7},"language-protobuf shiki shiki-themes github-light","syntax = \"proto3\";\npackage catalogue.v1;\noption go_package = \"github.com/org/services/catalogue/v1\";\n\nservice CatalogueService {\n  rpc GetProduct(GetProductRequest) returns (Product);\n  rpc ListProducts(ListProductsRequest) returns (stream Product);\n  rpc SearchProducts(SearchRequest) returns (SearchResponse);\n}\n\nmessage GetProductRequest {\n  string product_id = 1;\n}\n\nmessage ListProductsRequest {\n  int32 page_size = 1;\n  string page_token = 2;\n  string category_id = 3;\n}\n\nmessage Product {\n  string id = 1;\n  string name = 2;\n  string description = 3;\n  double price_eur = 4;\n  int32 stock_qty = 5;\n  repeated string image_urls = 6;\n  google.protobuf.Timestamp created_at = 7;\n}\n","protobuf",[87],{"type":34,"tag":49,"props":88,"children":89},{"__ignoreMap":7},[90,101,110,119,129,138,147,156,165,174,182,191,200,208,216,225,234,243,252,260,268,277,286,295,304,313,322,331,340],{"type":34,"tag":91,"props":92,"children":95},"span",{"class":93,"line":94},"line",1,[96],{"type":34,"tag":91,"props":97,"children":98},{},[99],{"type":40,"value":100},"syntax = \"proto3\";\n",{"type":34,"tag":91,"props":102,"children":104},{"class":93,"line":103},2,[105],{"type":34,"tag":91,"props":106,"children":107},{},[108],{"type":40,"value":109},"package catalogue.v1;\n",{"type":34,"tag":91,"props":111,"children":113},{"class":93,"line":112},3,[114],{"type":34,"tag":91,"props":115,"children":116},{},[117],{"type":40,"value":118},"option go_package = \"github.com/org/services/catalogue/v1\";\n",{"type":34,"tag":91,"props":120,"children":122},{"class":93,"line":121},4,[123],{"type":34,"tag":91,"props":124,"children":126},{"emptyLinePlaceholder":125},true,[127],{"type":40,"value":128},"\n",{"type":34,"tag":91,"props":130,"children":132},{"class":93,"line":131},5,[133],{"type":34,"tag":91,"props":134,"children":135},{},[136],{"type":40,"value":137},"service CatalogueService {\n",{"type":34,"tag":91,"props":139,"children":141},{"class":93,"line":140},6,[142],{"type":34,"tag":91,"props":143,"children":144},{},[145],{"type":40,"value":146},"  rpc GetProduct(GetProductRequest) returns (Product);\n",{"type":34,"tag":91,"props":148,"children":150},{"class":93,"line":149},7,[151],{"type":34,"tag":91,"props":152,"children":153},{},[154],{"type":40,"value":155},"  rpc ListProducts(ListProductsRequest) returns (stream Product);\n",{"type":34,"tag":91,"props":157,"children":159},{"class":93,"line":158},8,[160],{"type":34,"tag":91,"props":161,"children":162},{},[163],{"type":40,"value":164},"  rpc SearchProducts(SearchRequest) returns (SearchResponse);\n",{"type":34,"tag":91,"props":166,"children":168},{"class":93,"line":167},9,[169],{"type":34,"tag":91,"props":170,"children":171},{},[172],{"type":40,"value":173},"}\n",{"type":34,"tag":91,"props":175,"children":177},{"class":93,"line":176},10,[178],{"type":34,"tag":91,"props":179,"children":180},{"emptyLinePlaceholder":125},[181],{"type":40,"value":128},{"type":34,"tag":91,"props":183,"children":185},{"class":93,"line":184},11,[186],{"type":34,"tag":91,"props":187,"children":188},{},[189],{"type":40,"value":190},"message GetProductRequest {\n",{"type":34,"tag":91,"props":192,"children":194},{"class":93,"line":193},12,[195],{"type":34,"tag":91,"props":196,"children":197},{},[198],{"type":40,"value":199},"  string product_id = 1;\n",{"type":34,"tag":91,"props":201,"children":203},{"class":93,"line":202},13,[204],{"type":34,"tag":91,"props":205,"children":206},{},[207],{"type":40,"value":173},{"type":34,"tag":91,"props":209,"children":211},{"class":93,"line":210},14,[212],{"type":34,"tag":91,"props":213,"children":214},{"emptyLinePlaceholder":125},[215],{"type":40,"value":128},{"type":34,"tag":91,"props":217,"children":219},{"class":93,"line":218},15,[220],{"type":34,"tag":91,"props":221,"children":222},{},[223],{"type":40,"value":224},"message ListProductsRequest {\n",{"type":34,"tag":91,"props":226,"children":228},{"class":93,"line":227},16,[229],{"type":34,"tag":91,"props":230,"children":231},{},[232],{"type":40,"value":233},"  int32 page_size = 1;\n",{"type":34,"tag":91,"props":235,"children":237},{"class":93,"line":236},17,[238],{"type":34,"tag":91,"props":239,"children":240},{},[241],{"type":40,"value":242},"  string page_token = 2;\n",{"type":34,"tag":91,"props":244,"children":246},{"class":93,"line":245},18,[247],{"type":34,"tag":91,"props":248,"children":249},{},[250],{"type":40,"value":251},"  string category_id = 3;\n",{"type":34,"tag":91,"props":253,"children":255},{"class":93,"line":254},19,[256],{"type":34,"tag":91,"props":257,"children":258},{},[259],{"type":40,"value":173},{"type":34,"tag":91,"props":261,"children":263},{"class":93,"line":262},20,[264],{"type":34,"tag":91,"props":265,"children":266},{"emptyLinePlaceholder":125},[267],{"type":40,"value":128},{"type":34,"tag":91,"props":269,"children":271},{"class":93,"line":270},21,[272],{"type":34,"tag":91,"props":273,"children":274},{},[275],{"type":40,"value":276},"message Product {\n",{"type":34,"tag":91,"props":278,"children":280},{"class":93,"line":279},22,[281],{"type":34,"tag":91,"props":282,"children":283},{},[284],{"type":40,"value":285},"  string id = 1;\n",{"type":34,"tag":91,"props":287,"children":289},{"class":93,"line":288},23,[290],{"type":34,"tag":91,"props":291,"children":292},{},[293],{"type":40,"value":294},"  string name = 2;\n",{"type":34,"tag":91,"props":296,"children":298},{"class":93,"line":297},24,[299],{"type":34,"tag":91,"props":300,"children":301},{},[302],{"type":40,"value":303},"  string description = 3;\n",{"type":34,"tag":91,"props":305,"children":307},{"class":93,"line":306},25,[308],{"type":34,"tag":91,"props":309,"children":310},{},[311],{"type":40,"value":312},"  double price_eur = 4;\n",{"type":34,"tag":91,"props":314,"children":316},{"class":93,"line":315},26,[317],{"type":34,"tag":91,"props":318,"children":319},{},[320],{"type":40,"value":321},"  int32 stock_qty = 5;\n",{"type":34,"tag":91,"props":323,"children":325},{"class":93,"line":324},27,[326],{"type":34,"tag":91,"props":327,"children":328},{},[329],{"type":40,"value":330},"  repeated string image_urls = 6;\n",{"type":34,"tag":91,"props":332,"children":334},{"class":93,"line":333},28,[335],{"type":34,"tag":91,"props":336,"children":337},{},[338],{"type":40,"value":339},"  google.protobuf.Timestamp created_at = 7;\n",{"type":34,"tag":91,"props":341,"children":343},{"class":93,"line":342},29,[344],{"type":34,"tag":91,"props":345,"children":346},{},[347],{"type":40,"value":173},{"type":34,"tag":43,"props":349,"children":350},{},[351,353,359,361,367],{"type":40,"value":352},"Note ",{"type":34,"tag":49,"props":354,"children":356},{"className":355},[],[357],{"type":40,"value":358},"ListProducts",{"type":40,"value":360}," uses server-side streaming — the server sends a stream of ",{"type":34,"tag":49,"props":362,"children":364},{"className":363},[],[365],{"type":40,"value":366},"Product",{"type":40,"value":368}," messages, ideal for large paginated datasets without holding everything in memory.",{"type":34,"tag":35,"props":370,"children":372},{"id":371},"implementing-the-server",[373],{"type":40,"value":374},"Implementing the Server",{"type":34,"tag":81,"props":376,"children":380},{"className":377,"code":378,"language":379,"meta":7,"style":7},"language-go shiki shiki-themes github-light","package main\n\nimport (\n    \"context\"\n    \"log/slog\"\n    \"net\"\n\n    \"google.golang.org/grpc\"\n    \"google.golang.org/grpc/codes\"\n    \"google.golang.org/grpc/status\"\n    pb \"github.com/org/services/catalogue/v1\"\n)\n\ntype catalogueServer struct {\n    pb.UnimplementedCatalogueServiceServer\n    repo ProductRepository\n}\n\nfunc (s *catalogueServer) GetProduct(\n    ctx context.Context,\n    req *pb.GetProductRequest,\n) (*pb.Product, error) {\n    if req.ProductId == \"\" {\n        return nil, status.Error(codes.InvalidArgument, \"product_id is required\")\n    }\n\n    product, err := s.repo.FindByID(ctx, req.ProductId)\n    if err != nil {\n        if errors.Is(err, ErrNotFound) {\n            return nil, status.Errorf(codes.NotFound, \"product %q not found\", req.ProductId)\n        }\n        slog.ErrorContext(ctx, \"failed to fetch product\", \"id\", req.ProductId, \"err\", err)\n        return nil, status.Error(codes.Internal, \"internal error\")\n    }\n\n    return toProto(product), nil\n}\n\nfunc (s *catalogueServer) ListProducts(\n    req *pb.ListProductsRequest,\n    stream pb.CatalogueService_ListProductsServer,\n) error {\n    products, err := s.repo.List(stream.Context(), req.CategoryId, req.PageSize)\n    if err != nil {\n        return status.Error(codes.Internal, \"failed to list products\")\n    }\n\n    for _, p := range products {\n        if err := stream.Send(toProto(p)); err != nil {\n            return err  // Client disconnected\n        }\n    }\n    return nil\n}\n\nfunc main() {\n    lis, err := net.Listen(\"tcp\", \":50051\")\n    if err != nil {\n        slog.Error(\"failed to listen\", \"err\", err)\n        os.Exit(1)\n    }\n\n    s := grpc.NewServer(\n        grpc.ChainUnaryInterceptor(\n            otelgrpc.UnaryServerInterceptor(),   // Distributed tracing\n            recoveryInterceptor(),               // Panic recovery\n            loggingInterceptor(),                // Structured logging\n        ),\n        grpc.ChainStreamInterceptor(\n            otelgrpc.StreamServerInterceptor(),\n        ),\n    )\n\n    pb.RegisterCatalogueServiceServer(s, &catalogueServer{repo: newPostgresRepo()})\n\n    slog.Info(\"gRPC server listening\", \"addr\", \":50051\")\n    if err := s.Serve(lis); err != nil {\n        slog.Error(\"server failed\", \"err\", err)\n    }\n}\n","go",[381],{"type":34,"tag":49,"props":382,"children":383},{"__ignoreMap":7},[384,392,399,407,415,423,431,438,446,454,462,470,478,485,493,501,509,516,523,531,539,547,555,563,571,579,586,594,602,610,619,628,637,646,654,662,671,679,687,696,705,714,723,732,740,749,757,765,774,783,792,800,808,817,825,833,842,851,859,868,877,885,893,902,911,920,929,938,947,956,965,973,982,990,999,1007,1016,1025,1034,1042],{"type":34,"tag":91,"props":385,"children":386},{"class":93,"line":94},[387],{"type":34,"tag":91,"props":388,"children":389},{},[390],{"type":40,"value":391},"package main\n",{"type":34,"tag":91,"props":393,"children":394},{"class":93,"line":103},[395],{"type":34,"tag":91,"props":396,"children":397},{"emptyLinePlaceholder":125},[398],{"type":40,"value":128},{"type":34,"tag":91,"props":400,"children":401},{"class":93,"line":112},[402],{"type":34,"tag":91,"props":403,"children":404},{},[405],{"type":40,"value":406},"import (\n",{"type":34,"tag":91,"props":408,"children":409},{"class":93,"line":121},[410],{"type":34,"tag":91,"props":411,"children":412},{},[413],{"type":40,"value":414},"    \"context\"\n",{"type":34,"tag":91,"props":416,"children":417},{"class":93,"line":131},[418],{"type":34,"tag":91,"props":419,"children":420},{},[421],{"type":40,"value":422},"    \"log/slog\"\n",{"type":34,"tag":91,"props":424,"children":425},{"class":93,"line":140},[426],{"type":34,"tag":91,"props":427,"children":428},{},[429],{"type":40,"value":430},"    \"net\"\n",{"type":34,"tag":91,"props":432,"children":433},{"class":93,"line":149},[434],{"type":34,"tag":91,"props":435,"children":436},{"emptyLinePlaceholder":125},[437],{"type":40,"value":128},{"type":34,"tag":91,"props":439,"children":440},{"class":93,"line":158},[441],{"type":34,"tag":91,"props":442,"children":443},{},[444],{"type":40,"value":445},"    \"google.golang.org/grpc\"\n",{"type":34,"tag":91,"props":447,"children":448},{"class":93,"line":167},[449],{"type":34,"tag":91,"props":450,"children":451},{},[452],{"type":40,"value":453},"    \"google.golang.org/grpc/codes\"\n",{"type":34,"tag":91,"props":455,"children":456},{"class":93,"line":176},[457],{"type":34,"tag":91,"props":458,"children":459},{},[460],{"type":40,"value":461},"    \"google.golang.org/grpc/status\"\n",{"type":34,"tag":91,"props":463,"children":464},{"class":93,"line":184},[465],{"type":34,"tag":91,"props":466,"children":467},{},[468],{"type":40,"value":469},"    pb \"github.com/org/services/catalogue/v1\"\n",{"type":34,"tag":91,"props":471,"children":472},{"class":93,"line":193},[473],{"type":34,"tag":91,"props":474,"children":475},{},[476],{"type":40,"value":477},")\n",{"type":34,"tag":91,"props":479,"children":480},{"class":93,"line":202},[481],{"type":34,"tag":91,"props":482,"children":483},{"emptyLinePlaceholder":125},[484],{"type":40,"value":128},{"type":34,"tag":91,"props":486,"children":487},{"class":93,"line":210},[488],{"type":34,"tag":91,"props":489,"children":490},{},[491],{"type":40,"value":492},"type catalogueServer struct {\n",{"type":34,"tag":91,"props":494,"children":495},{"class":93,"line":218},[496],{"type":34,"tag":91,"props":497,"children":498},{},[499],{"type":40,"value":500},"    pb.UnimplementedCatalogueServiceServer\n",{"type":34,"tag":91,"props":502,"children":503},{"class":93,"line":227},[504],{"type":34,"tag":91,"props":505,"children":506},{},[507],{"type":40,"value":508},"    repo ProductRepository\n",{"type":34,"tag":91,"props":510,"children":511},{"class":93,"line":236},[512],{"type":34,"tag":91,"props":513,"children":514},{},[515],{"type":40,"value":173},{"type":34,"tag":91,"props":517,"children":518},{"class":93,"line":245},[519],{"type":34,"tag":91,"props":520,"children":521},{"emptyLinePlaceholder":125},[522],{"type":40,"value":128},{"type":34,"tag":91,"props":524,"children":525},{"class":93,"line":254},[526],{"type":34,"tag":91,"props":527,"children":528},{},[529],{"type":40,"value":530},"func (s *catalogueServer) GetProduct(\n",{"type":34,"tag":91,"props":532,"children":533},{"class":93,"line":262},[534],{"type":34,"tag":91,"props":535,"children":536},{},[537],{"type":40,"value":538},"    ctx context.Context,\n",{"type":34,"tag":91,"props":540,"children":541},{"class":93,"line":270},[542],{"type":34,"tag":91,"props":543,"children":544},{},[545],{"type":40,"value":546},"    req *pb.GetProductRequest,\n",{"type":34,"tag":91,"props":548,"children":549},{"class":93,"line":279},[550],{"type":34,"tag":91,"props":551,"children":552},{},[553],{"type":40,"value":554},") (*pb.Product, error) {\n",{"type":34,"tag":91,"props":556,"children":557},{"class":93,"line":288},[558],{"type":34,"tag":91,"props":559,"children":560},{},[561],{"type":40,"value":562},"    if req.ProductId == \"\" {\n",{"type":34,"tag":91,"props":564,"children":565},{"class":93,"line":297},[566],{"type":34,"tag":91,"props":567,"children":568},{},[569],{"type":40,"value":570},"        return nil, status.Error(codes.InvalidArgument, \"product_id is required\")\n",{"type":34,"tag":91,"props":572,"children":573},{"class":93,"line":306},[574],{"type":34,"tag":91,"props":575,"children":576},{},[577],{"type":40,"value":578},"    }\n",{"type":34,"tag":91,"props":580,"children":581},{"class":93,"line":315},[582],{"type":34,"tag":91,"props":583,"children":584},{"emptyLinePlaceholder":125},[585],{"type":40,"value":128},{"type":34,"tag":91,"props":587,"children":588},{"class":93,"line":324},[589],{"type":34,"tag":91,"props":590,"children":591},{},[592],{"type":40,"value":593},"    product, err := s.repo.FindByID(ctx, req.ProductId)\n",{"type":34,"tag":91,"props":595,"children":596},{"class":93,"line":333},[597],{"type":34,"tag":91,"props":598,"children":599},{},[600],{"type":40,"value":601},"    if err != nil {\n",{"type":34,"tag":91,"props":603,"children":604},{"class":93,"line":342},[605],{"type":34,"tag":91,"props":606,"children":607},{},[608],{"type":40,"value":609},"        if errors.Is(err, ErrNotFound) {\n",{"type":34,"tag":91,"props":611,"children":613},{"class":93,"line":612},30,[614],{"type":34,"tag":91,"props":615,"children":616},{},[617],{"type":40,"value":618},"            return nil, status.Errorf(codes.NotFound, \"product %q not found\", req.ProductId)\n",{"type":34,"tag":91,"props":620,"children":622},{"class":93,"line":621},31,[623],{"type":34,"tag":91,"props":624,"children":625},{},[626],{"type":40,"value":627},"        }\n",{"type":34,"tag":91,"props":629,"children":631},{"class":93,"line":630},32,[632],{"type":34,"tag":91,"props":633,"children":634},{},[635],{"type":40,"value":636},"        slog.ErrorContext(ctx, \"failed to fetch product\", \"id\", req.ProductId, \"err\", err)\n",{"type":34,"tag":91,"props":638,"children":640},{"class":93,"line":639},33,[641],{"type":34,"tag":91,"props":642,"children":643},{},[644],{"type":40,"value":645},"        return nil, status.Error(codes.Internal, \"internal error\")\n",{"type":34,"tag":91,"props":647,"children":649},{"class":93,"line":648},34,[650],{"type":34,"tag":91,"props":651,"children":652},{},[653],{"type":40,"value":578},{"type":34,"tag":91,"props":655,"children":657},{"class":93,"line":656},35,[658],{"type":34,"tag":91,"props":659,"children":660},{"emptyLinePlaceholder":125},[661],{"type":40,"value":128},{"type":34,"tag":91,"props":663,"children":665},{"class":93,"line":664},36,[666],{"type":34,"tag":91,"props":667,"children":668},{},[669],{"type":40,"value":670},"    return toProto(product), nil\n",{"type":34,"tag":91,"props":672,"children":674},{"class":93,"line":673},37,[675],{"type":34,"tag":91,"props":676,"children":677},{},[678],{"type":40,"value":173},{"type":34,"tag":91,"props":680,"children":682},{"class":93,"line":681},38,[683],{"type":34,"tag":91,"props":684,"children":685},{"emptyLinePlaceholder":125},[686],{"type":40,"value":128},{"type":34,"tag":91,"props":688,"children":690},{"class":93,"line":689},39,[691],{"type":34,"tag":91,"props":692,"children":693},{},[694],{"type":40,"value":695},"func (s *catalogueServer) ListProducts(\n",{"type":34,"tag":91,"props":697,"children":699},{"class":93,"line":698},40,[700],{"type":34,"tag":91,"props":701,"children":702},{},[703],{"type":40,"value":704},"    req *pb.ListProductsRequest,\n",{"type":34,"tag":91,"props":706,"children":708},{"class":93,"line":707},41,[709],{"type":34,"tag":91,"props":710,"children":711},{},[712],{"type":40,"value":713},"    stream pb.CatalogueService_ListProductsServer,\n",{"type":34,"tag":91,"props":715,"children":717},{"class":93,"line":716},42,[718],{"type":34,"tag":91,"props":719,"children":720},{},[721],{"type":40,"value":722},") error {\n",{"type":34,"tag":91,"props":724,"children":726},{"class":93,"line":725},43,[727],{"type":34,"tag":91,"props":728,"children":729},{},[730],{"type":40,"value":731},"    products, err := s.repo.List(stream.Context(), req.CategoryId, req.PageSize)\n",{"type":34,"tag":91,"props":733,"children":735},{"class":93,"line":734},44,[736],{"type":34,"tag":91,"props":737,"children":738},{},[739],{"type":40,"value":601},{"type":34,"tag":91,"props":741,"children":743},{"class":93,"line":742},45,[744],{"type":34,"tag":91,"props":745,"children":746},{},[747],{"type":40,"value":748},"        return status.Error(codes.Internal, \"failed to list products\")\n",{"type":34,"tag":91,"props":750,"children":752},{"class":93,"line":751},46,[753],{"type":34,"tag":91,"props":754,"children":755},{},[756],{"type":40,"value":578},{"type":34,"tag":91,"props":758,"children":760},{"class":93,"line":759},47,[761],{"type":34,"tag":91,"props":762,"children":763},{"emptyLinePlaceholder":125},[764],{"type":40,"value":128},{"type":34,"tag":91,"props":766,"children":768},{"class":93,"line":767},48,[769],{"type":34,"tag":91,"props":770,"children":771},{},[772],{"type":40,"value":773},"    for _, p := range products {\n",{"type":34,"tag":91,"props":775,"children":777},{"class":93,"line":776},49,[778],{"type":34,"tag":91,"props":779,"children":780},{},[781],{"type":40,"value":782},"        if err := stream.Send(toProto(p)); err != nil {\n",{"type":34,"tag":91,"props":784,"children":786},{"class":93,"line":785},50,[787],{"type":34,"tag":91,"props":788,"children":789},{},[790],{"type":40,"value":791},"            return err  // Client disconnected\n",{"type":34,"tag":91,"props":793,"children":795},{"class":93,"line":794},51,[796],{"type":34,"tag":91,"props":797,"children":798},{},[799],{"type":40,"value":627},{"type":34,"tag":91,"props":801,"children":803},{"class":93,"line":802},52,[804],{"type":34,"tag":91,"props":805,"children":806},{},[807],{"type":40,"value":578},{"type":34,"tag":91,"props":809,"children":811},{"class":93,"line":810},53,[812],{"type":34,"tag":91,"props":813,"children":814},{},[815],{"type":40,"value":816},"    return nil\n",{"type":34,"tag":91,"props":818,"children":820},{"class":93,"line":819},54,[821],{"type":34,"tag":91,"props":822,"children":823},{},[824],{"type":40,"value":173},{"type":34,"tag":91,"props":826,"children":828},{"class":93,"line":827},55,[829],{"type":34,"tag":91,"props":830,"children":831},{"emptyLinePlaceholder":125},[832],{"type":40,"value":128},{"type":34,"tag":91,"props":834,"children":836},{"class":93,"line":835},56,[837],{"type":34,"tag":91,"props":838,"children":839},{},[840],{"type":40,"value":841},"func main() {\n",{"type":34,"tag":91,"props":843,"children":845},{"class":93,"line":844},57,[846],{"type":34,"tag":91,"props":847,"children":848},{},[849],{"type":40,"value":850},"    lis, err := net.Listen(\"tcp\", \":50051\")\n",{"type":34,"tag":91,"props":852,"children":854},{"class":93,"line":853},58,[855],{"type":34,"tag":91,"props":856,"children":857},{},[858],{"type":40,"value":601},{"type":34,"tag":91,"props":860,"children":862},{"class":93,"line":861},59,[863],{"type":34,"tag":91,"props":864,"children":865},{},[866],{"type":40,"value":867},"        slog.Error(\"failed to listen\", \"err\", err)\n",{"type":34,"tag":91,"props":869,"children":871},{"class":93,"line":870},60,[872],{"type":34,"tag":91,"props":873,"children":874},{},[875],{"type":40,"value":876},"        os.Exit(1)\n",{"type":34,"tag":91,"props":878,"children":880},{"class":93,"line":879},61,[881],{"type":34,"tag":91,"props":882,"children":883},{},[884],{"type":40,"value":578},{"type":34,"tag":91,"props":886,"children":888},{"class":93,"line":887},62,[889],{"type":34,"tag":91,"props":890,"children":891},{"emptyLinePlaceholder":125},[892],{"type":40,"value":128},{"type":34,"tag":91,"props":894,"children":896},{"class":93,"line":895},63,[897],{"type":34,"tag":91,"props":898,"children":899},{},[900],{"type":40,"value":901},"    s := grpc.NewServer(\n",{"type":34,"tag":91,"props":903,"children":905},{"class":93,"line":904},64,[906],{"type":34,"tag":91,"props":907,"children":908},{},[909],{"type":40,"value":910},"        grpc.ChainUnaryInterceptor(\n",{"type":34,"tag":91,"props":912,"children":914},{"class":93,"line":913},65,[915],{"type":34,"tag":91,"props":916,"children":917},{},[918],{"type":40,"value":919},"            otelgrpc.UnaryServerInterceptor(),   // Distributed tracing\n",{"type":34,"tag":91,"props":921,"children":923},{"class":93,"line":922},66,[924],{"type":34,"tag":91,"props":925,"children":926},{},[927],{"type":40,"value":928},"            recoveryInterceptor(),               // Panic recovery\n",{"type":34,"tag":91,"props":930,"children":932},{"class":93,"line":931},67,[933],{"type":34,"tag":91,"props":934,"children":935},{},[936],{"type":40,"value":937},"            loggingInterceptor(),                // Structured logging\n",{"type":34,"tag":91,"props":939,"children":941},{"class":93,"line":940},68,[942],{"type":34,"tag":91,"props":943,"children":944},{},[945],{"type":40,"value":946},"        ),\n",{"type":34,"tag":91,"props":948,"children":950},{"class":93,"line":949},69,[951],{"type":34,"tag":91,"props":952,"children":953},{},[954],{"type":40,"value":955},"        grpc.ChainStreamInterceptor(\n",{"type":34,"tag":91,"props":957,"children":959},{"class":93,"line":958},70,[960],{"type":34,"tag":91,"props":961,"children":962},{},[963],{"type":40,"value":964},"            otelgrpc.StreamServerInterceptor(),\n",{"type":34,"tag":91,"props":966,"children":968},{"class":93,"line":967},71,[969],{"type":34,"tag":91,"props":970,"children":971},{},[972],{"type":40,"value":946},{"type":34,"tag":91,"props":974,"children":976},{"class":93,"line":975},72,[977],{"type":34,"tag":91,"props":978,"children":979},{},[980],{"type":40,"value":981},"    )\n",{"type":34,"tag":91,"props":983,"children":985},{"class":93,"line":984},73,[986],{"type":34,"tag":91,"props":987,"children":988},{"emptyLinePlaceholder":125},[989],{"type":40,"value":128},{"type":34,"tag":91,"props":991,"children":993},{"class":93,"line":992},74,[994],{"type":34,"tag":91,"props":995,"children":996},{},[997],{"type":40,"value":998},"    pb.RegisterCatalogueServiceServer(s, &catalogueServer{repo: newPostgresRepo()})\n",{"type":34,"tag":91,"props":1000,"children":1002},{"class":93,"line":1001},75,[1003],{"type":34,"tag":91,"props":1004,"children":1005},{"emptyLinePlaceholder":125},[1006],{"type":40,"value":128},{"type":34,"tag":91,"props":1008,"children":1010},{"class":93,"line":1009},76,[1011],{"type":34,"tag":91,"props":1012,"children":1013},{},[1014],{"type":40,"value":1015},"    slog.Info(\"gRPC server listening\", \"addr\", \":50051\")\n",{"type":34,"tag":91,"props":1017,"children":1019},{"class":93,"line":1018},77,[1020],{"type":34,"tag":91,"props":1021,"children":1022},{},[1023],{"type":40,"value":1024},"    if err := s.Serve(lis); err != nil {\n",{"type":34,"tag":91,"props":1026,"children":1028},{"class":93,"line":1027},78,[1029],{"type":34,"tag":91,"props":1030,"children":1031},{},[1032],{"type":40,"value":1033},"        slog.Error(\"server failed\", \"err\", err)\n",{"type":34,"tag":91,"props":1035,"children":1037},{"class":93,"line":1036},79,[1038],{"type":34,"tag":91,"props":1039,"children":1040},{},[1041],{"type":40,"value":578},{"type":34,"tag":91,"props":1043,"children":1045},{"class":93,"line":1044},80,[1046],{"type":34,"tag":91,"props":1047,"children":1048},{},[1049],{"type":40,"value":173},{"type":34,"tag":43,"props":1051,"children":1052},{},[1053,1055,1061],{"type":40,"value":1054},"Always embed ",{"type":34,"tag":49,"props":1056,"children":1058},{"className":1057},[],[1059],{"type":40,"value":1060},"UnimplementedCatalogueServiceServer",{"type":40,"value":1062}," — it future-proofs your server against new RPC methods added to the proto without breaking existing deployments.",{"type":34,"tag":35,"props":1064,"children":1066},{"id":1065},"circuit-breaking-for-resilience",[1067],{"type":40,"value":1068},"Circuit Breaking for Resilience",{"type":34,"tag":43,"props":1070,"children":1071},{},[1072],{"type":40,"value":1073},"A slow upstream service can cascade into a system-wide outage if callers keep queuing requests. A circuit breaker opens when failure rates exceed a threshold, failing fast and giving the upstream time to recover:",{"type":34,"tag":81,"props":1075,"children":1077},{"className":377,"code":1076,"language":379,"meta":7,"style":7},"import \"github.com/sony/gobreaker/v2\"\n\ntype resilientCatalogueClient struct {\n    inner pb.CatalogueServiceClient\n    cb    *gobreaker.CircuitBreaker[*pb.Product]\n}\n\nfunc newResilientClient(conn *grpc.ClientConn) *resilientCatalogueClient {\n    cb := gobreaker.NewCircuitBreaker[*pb.Product](gobreaker.Settings{\n        Name: \"catalogue-service\",\n        ReadyToTrip: func(counts gobreaker.Counts) bool {\n            // Open after >60% failure rate with at least 5 requests\n            return counts.Requests >= 5 &&\n                float64(counts.TotalFailures)/float64(counts.Requests) > 0.6\n        },\n        OnStateChange: func(name string, from, to gobreaker.State) {\n            slog.Info(\"circuit breaker state change\",\n                \"service\", name, \"from\", from, \"to\", to)\n        },\n        Timeout: 30 * time.Second,\n    })\n\n    return &resilientCatalogueClient{\n        inner: pb.NewCatalogueServiceClient(conn),\n        cb:    cb,\n    }\n}\n\nfunc (c *resilientCatalogueClient) GetProduct(\n    ctx context.Context,\n    req *pb.GetProductRequest,\n) (*pb.Product, error) {\n    return c.cb.Execute(func() (*pb.Product, error) {\n        return c.inner.GetProduct(ctx, req)\n    })\n}\n",[1078],{"type":34,"tag":49,"props":1079,"children":1080},{"__ignoreMap":7},[1081,1089,1096,1104,1112,1120,1127,1134,1142,1150,1158,1166,1174,1182,1190,1198,1206,1214,1222,1229,1237,1245,1252,1260,1268,1276,1283,1290,1297,1305,1312,1319,1326,1334,1342,1349],{"type":34,"tag":91,"props":1082,"children":1083},{"class":93,"line":94},[1084],{"type":34,"tag":91,"props":1085,"children":1086},{},[1087],{"type":40,"value":1088},"import \"github.com/sony/gobreaker/v2\"\n",{"type":34,"tag":91,"props":1090,"children":1091},{"class":93,"line":103},[1092],{"type":34,"tag":91,"props":1093,"children":1094},{"emptyLinePlaceholder":125},[1095],{"type":40,"value":128},{"type":34,"tag":91,"props":1097,"children":1098},{"class":93,"line":112},[1099],{"type":34,"tag":91,"props":1100,"children":1101},{},[1102],{"type":40,"value":1103},"type resilientCatalogueClient struct {\n",{"type":34,"tag":91,"props":1105,"children":1106},{"class":93,"line":121},[1107],{"type":34,"tag":91,"props":1108,"children":1109},{},[1110],{"type":40,"value":1111},"    inner pb.CatalogueServiceClient\n",{"type":34,"tag":91,"props":1113,"children":1114},{"class":93,"line":131},[1115],{"type":34,"tag":91,"props":1116,"children":1117},{},[1118],{"type":40,"value":1119},"    cb    *gobreaker.CircuitBreaker[*pb.Product]\n",{"type":34,"tag":91,"props":1121,"children":1122},{"class":93,"line":140},[1123],{"type":34,"tag":91,"props":1124,"children":1125},{},[1126],{"type":40,"value":173},{"type":34,"tag":91,"props":1128,"children":1129},{"class":93,"line":149},[1130],{"type":34,"tag":91,"props":1131,"children":1132},{"emptyLinePlaceholder":125},[1133],{"type":40,"value":128},{"type":34,"tag":91,"props":1135,"children":1136},{"class":93,"line":158},[1137],{"type":34,"tag":91,"props":1138,"children":1139},{},[1140],{"type":40,"value":1141},"func newResilientClient(conn *grpc.ClientConn) *resilientCatalogueClient {\n",{"type":34,"tag":91,"props":1143,"children":1144},{"class":93,"line":167},[1145],{"type":34,"tag":91,"props":1146,"children":1147},{},[1148],{"type":40,"value":1149},"    cb := gobreaker.NewCircuitBreaker[*pb.Product](gobreaker.Settings{\n",{"type":34,"tag":91,"props":1151,"children":1152},{"class":93,"line":176},[1153],{"type":34,"tag":91,"props":1154,"children":1155},{},[1156],{"type":40,"value":1157},"        Name: \"catalogue-service\",\n",{"type":34,"tag":91,"props":1159,"children":1160},{"class":93,"line":184},[1161],{"type":34,"tag":91,"props":1162,"children":1163},{},[1164],{"type":40,"value":1165},"        ReadyToTrip: func(counts gobreaker.Counts) bool {\n",{"type":34,"tag":91,"props":1167,"children":1168},{"class":93,"line":193},[1169],{"type":34,"tag":91,"props":1170,"children":1171},{},[1172],{"type":40,"value":1173},"            // Open after >60% failure rate with at least 5 requests\n",{"type":34,"tag":91,"props":1175,"children":1176},{"class":93,"line":202},[1177],{"type":34,"tag":91,"props":1178,"children":1179},{},[1180],{"type":40,"value":1181},"            return counts.Requests >= 5 &&\n",{"type":34,"tag":91,"props":1183,"children":1184},{"class":93,"line":210},[1185],{"type":34,"tag":91,"props":1186,"children":1187},{},[1188],{"type":40,"value":1189},"                float64(counts.TotalFailures)/float64(counts.Requests) > 0.6\n",{"type":34,"tag":91,"props":1191,"children":1192},{"class":93,"line":218},[1193],{"type":34,"tag":91,"props":1194,"children":1195},{},[1196],{"type":40,"value":1197},"        },\n",{"type":34,"tag":91,"props":1199,"children":1200},{"class":93,"line":227},[1201],{"type":34,"tag":91,"props":1202,"children":1203},{},[1204],{"type":40,"value":1205},"        OnStateChange: func(name string, from, to gobreaker.State) {\n",{"type":34,"tag":91,"props":1207,"children":1208},{"class":93,"line":236},[1209],{"type":34,"tag":91,"props":1210,"children":1211},{},[1212],{"type":40,"value":1213},"            slog.Info(\"circuit breaker state change\",\n",{"type":34,"tag":91,"props":1215,"children":1216},{"class":93,"line":245},[1217],{"type":34,"tag":91,"props":1218,"children":1219},{},[1220],{"type":40,"value":1221},"                \"service\", name, \"from\", from, \"to\", to)\n",{"type":34,"tag":91,"props":1223,"children":1224},{"class":93,"line":254},[1225],{"type":34,"tag":91,"props":1226,"children":1227},{},[1228],{"type":40,"value":1197},{"type":34,"tag":91,"props":1230,"children":1231},{"class":93,"line":262},[1232],{"type":34,"tag":91,"props":1233,"children":1234},{},[1235],{"type":40,"value":1236},"        Timeout: 30 * time.Second,\n",{"type":34,"tag":91,"props":1238,"children":1239},{"class":93,"line":270},[1240],{"type":34,"tag":91,"props":1241,"children":1242},{},[1243],{"type":40,"value":1244},"    })\n",{"type":34,"tag":91,"props":1246,"children":1247},{"class":93,"line":279},[1248],{"type":34,"tag":91,"props":1249,"children":1250},{"emptyLinePlaceholder":125},[1251],{"type":40,"value":128},{"type":34,"tag":91,"props":1253,"children":1254},{"class":93,"line":288},[1255],{"type":34,"tag":91,"props":1256,"children":1257},{},[1258],{"type":40,"value":1259},"    return &resilientCatalogueClient{\n",{"type":34,"tag":91,"props":1261,"children":1262},{"class":93,"line":297},[1263],{"type":34,"tag":91,"props":1264,"children":1265},{},[1266],{"type":40,"value":1267},"        inner: pb.NewCatalogueServiceClient(conn),\n",{"type":34,"tag":91,"props":1269,"children":1270},{"class":93,"line":306},[1271],{"type":34,"tag":91,"props":1272,"children":1273},{},[1274],{"type":40,"value":1275},"        cb:    cb,\n",{"type":34,"tag":91,"props":1277,"children":1278},{"class":93,"line":315},[1279],{"type":34,"tag":91,"props":1280,"children":1281},{},[1282],{"type":40,"value":578},{"type":34,"tag":91,"props":1284,"children":1285},{"class":93,"line":324},[1286],{"type":34,"tag":91,"props":1287,"children":1288},{},[1289],{"type":40,"value":173},{"type":34,"tag":91,"props":1291,"children":1292},{"class":93,"line":333},[1293],{"type":34,"tag":91,"props":1294,"children":1295},{"emptyLinePlaceholder":125},[1296],{"type":40,"value":128},{"type":34,"tag":91,"props":1298,"children":1299},{"class":93,"line":342},[1300],{"type":34,"tag":91,"props":1301,"children":1302},{},[1303],{"type":40,"value":1304},"func (c *resilientCatalogueClient) GetProduct(\n",{"type":34,"tag":91,"props":1306,"children":1307},{"class":93,"line":612},[1308],{"type":34,"tag":91,"props":1309,"children":1310},{},[1311],{"type":40,"value":538},{"type":34,"tag":91,"props":1313,"children":1314},{"class":93,"line":621},[1315],{"type":34,"tag":91,"props":1316,"children":1317},{},[1318],{"type":40,"value":546},{"type":34,"tag":91,"props":1320,"children":1321},{"class":93,"line":630},[1322],{"type":34,"tag":91,"props":1323,"children":1324},{},[1325],{"type":40,"value":554},{"type":34,"tag":91,"props":1327,"children":1328},{"class":93,"line":639},[1329],{"type":34,"tag":91,"props":1330,"children":1331},{},[1332],{"type":40,"value":1333},"    return c.cb.Execute(func() (*pb.Product, error) {\n",{"type":34,"tag":91,"props":1335,"children":1336},{"class":93,"line":648},[1337],{"type":34,"tag":91,"props":1338,"children":1339},{},[1340],{"type":40,"value":1341},"        return c.inner.GetProduct(ctx, req)\n",{"type":34,"tag":91,"props":1343,"children":1344},{"class":93,"line":656},[1345],{"type":34,"tag":91,"props":1346,"children":1347},{},[1348],{"type":40,"value":1244},{"type":34,"tag":91,"props":1350,"children":1351},{"class":93,"line":664},[1352],{"type":34,"tag":91,"props":1353,"children":1354},{},[1355],{"type":40,"value":173},{"type":34,"tag":35,"props":1357,"children":1359},{"id":1358},"service-discovery-with-consul",[1360],{"type":40,"value":1361},"Service Discovery with Consul",{"type":34,"tag":43,"props":1363,"children":1364},{},[1365],{"type":40,"value":1366},"In a dynamic container environment, service IP addresses change constantly. Register services with Consul on startup and use gRPC's native name resolver to route to healthy instances:",{"type":34,"tag":81,"props":1368,"children":1370},{"className":377,"code":1369,"language":379,"meta":7,"style":7},"func registerWithConsul(port int) {\n    client, _ := api.NewClient(api.DefaultConfig())\n\n    check := &api.AgentServiceCheck{\n        GRPC:                           fmt.Sprintf(\"host.docker.internal:%d\", port),\n        Interval:                       \"10s\",\n        Timeout:                        \"2s\",\n        DeregisterCriticalServiceAfter: \"30s\",\n    }\n\n    client.Agent().ServiceRegister(&api.AgentServiceRegistration{\n        ID:      fmt.Sprintf(\"catalogue-service-%d\", port),\n        Name:    \"catalogue-service\",\n        Port:    port,\n        Tags:    []string{\"grpc\", \"v1\"},\n        Check:   check,\n    })\n}\n",[1371],{"type":34,"tag":49,"props":1372,"children":1373},{"__ignoreMap":7},[1374,1382,1390,1397,1405,1413,1421,1429,1437,1444,1451,1459,1467,1475,1483,1491,1499,1506],{"type":34,"tag":91,"props":1375,"children":1376},{"class":93,"line":94},[1377],{"type":34,"tag":91,"props":1378,"children":1379},{},[1380],{"type":40,"value":1381},"func registerWithConsul(port int) {\n",{"type":34,"tag":91,"props":1383,"children":1384},{"class":93,"line":103},[1385],{"type":34,"tag":91,"props":1386,"children":1387},{},[1388],{"type":40,"value":1389},"    client, _ := api.NewClient(api.DefaultConfig())\n",{"type":34,"tag":91,"props":1391,"children":1392},{"class":93,"line":112},[1393],{"type":34,"tag":91,"props":1394,"children":1395},{"emptyLinePlaceholder":125},[1396],{"type":40,"value":128},{"type":34,"tag":91,"props":1398,"children":1399},{"class":93,"line":121},[1400],{"type":34,"tag":91,"props":1401,"children":1402},{},[1403],{"type":40,"value":1404},"    check := &api.AgentServiceCheck{\n",{"type":34,"tag":91,"props":1406,"children":1407},{"class":93,"line":131},[1408],{"type":34,"tag":91,"props":1409,"children":1410},{},[1411],{"type":40,"value":1412},"        GRPC:                           fmt.Sprintf(\"host.docker.internal:%d\", port),\n",{"type":34,"tag":91,"props":1414,"children":1415},{"class":93,"line":140},[1416],{"type":34,"tag":91,"props":1417,"children":1418},{},[1419],{"type":40,"value":1420},"        Interval:                       \"10s\",\n",{"type":34,"tag":91,"props":1422,"children":1423},{"class":93,"line":149},[1424],{"type":34,"tag":91,"props":1425,"children":1426},{},[1427],{"type":40,"value":1428},"        Timeout:                        \"2s\",\n",{"type":34,"tag":91,"props":1430,"children":1431},{"class":93,"line":158},[1432],{"type":34,"tag":91,"props":1433,"children":1434},{},[1435],{"type":40,"value":1436},"        DeregisterCriticalServiceAfter: \"30s\",\n",{"type":34,"tag":91,"props":1438,"children":1439},{"class":93,"line":167},[1440],{"type":34,"tag":91,"props":1441,"children":1442},{},[1443],{"type":40,"value":578},{"type":34,"tag":91,"props":1445,"children":1446},{"class":93,"line":176},[1447],{"type":34,"tag":91,"props":1448,"children":1449},{"emptyLinePlaceholder":125},[1450],{"type":40,"value":128},{"type":34,"tag":91,"props":1452,"children":1453},{"class":93,"line":184},[1454],{"type":34,"tag":91,"props":1455,"children":1456},{},[1457],{"type":40,"value":1458},"    client.Agent().ServiceRegister(&api.AgentServiceRegistration{\n",{"type":34,"tag":91,"props":1460,"children":1461},{"class":93,"line":193},[1462],{"type":34,"tag":91,"props":1463,"children":1464},{},[1465],{"type":40,"value":1466},"        ID:      fmt.Sprintf(\"catalogue-service-%d\", port),\n",{"type":34,"tag":91,"props":1468,"children":1469},{"class":93,"line":202},[1470],{"type":34,"tag":91,"props":1471,"children":1472},{},[1473],{"type":40,"value":1474},"        Name:    \"catalogue-service\",\n",{"type":34,"tag":91,"props":1476,"children":1477},{"class":93,"line":210},[1478],{"type":34,"tag":91,"props":1479,"children":1480},{},[1481],{"type":40,"value":1482},"        Port:    port,\n",{"type":34,"tag":91,"props":1484,"children":1485},{"class":93,"line":218},[1486],{"type":34,"tag":91,"props":1487,"children":1488},{},[1489],{"type":40,"value":1490},"        Tags:    []string{\"grpc\", \"v1\"},\n",{"type":34,"tag":91,"props":1492,"children":1493},{"class":93,"line":227},[1494],{"type":34,"tag":91,"props":1495,"children":1496},{},[1497],{"type":40,"value":1498},"        Check:   check,\n",{"type":34,"tag":91,"props":1500,"children":1501},{"class":93,"line":236},[1502],{"type":34,"tag":91,"props":1503,"children":1504},{},[1505],{"type":40,"value":1244},{"type":34,"tag":91,"props":1507,"children":1508},{"class":93,"line":245},[1509],{"type":34,"tag":91,"props":1510,"children":1511},{},[1512],{"type":40,"value":173},{"type":34,"tag":43,"props":1514,"children":1515},{},[1516,1518,1524],{"type":40,"value":1517},"On the client side, use ",{"type":34,"tag":49,"props":1519,"children":1521},{"className":1520},[],[1522],{"type":40,"value":1523},"consul://catalogue-service",{"type":40,"value":1525}," as the dial target with a Consul resolver plugin — gRPC's client-side load balancing distributes calls across all healthy replicas automatically.",{"type":34,"tag":35,"props":1527,"children":1529},{"id":1528},"observability-metrics-tracing-and-logging",[1530],{"type":40,"value":1531},"Observability: Metrics, Tracing, and Logging",{"type":34,"tag":43,"props":1533,"children":1534},{},[1535],{"type":40,"value":1536},"Distributed systems are opaque without instrumentation. The Go ecosystem has excellent OpenTelemetry support:",{"type":34,"tag":81,"props":1538,"children":1540},{"className":377,"code":1539,"language":379,"meta":7,"style":7},"func initTelemetry(ctx context.Context, serviceName string) func() {\n    // OTLP exporter → Grafana Tempo / Jaeger / Azure Monitor\n    exporter, _ := otlptracegrpc.New(ctx,\n        otlptracegrpc.WithEndpoint(\"otel-collector:4317\"),\n        otlptracegrpc.WithInsecure(),\n    )\n\n    tp := sdktrace.NewTracerProvider(\n        sdktrace.WithBatcher(exporter),\n        sdktrace.WithResource(resource.NewWithAttributes(\n            semconv.SchemaURL,\n            semconv.ServiceName(serviceName),\n            semconv.ServiceVersion(\"v2.4.1\"),\n        )),\n    )\n\n    otel.SetTracerProvider(tp)\n    otel.SetTextMapPropagator(propagation.TraceContext{})\n\n    // Prometheus metrics via grpc-go interceptors\n    grpcmetrics.EnableHandlingTimeHistogram()\n\n    return func() { tp.Shutdown(ctx) }\n}\n",[1541],{"type":34,"tag":49,"props":1542,"children":1543},{"__ignoreMap":7},[1544,1552,1560,1568,1576,1584,1591,1598,1606,1614,1622,1630,1638,1646,1654,1661,1668,1676,1684,1691,1699,1707,1714,1722],{"type":34,"tag":91,"props":1545,"children":1546},{"class":93,"line":94},[1547],{"type":34,"tag":91,"props":1548,"children":1549},{},[1550],{"type":40,"value":1551},"func initTelemetry(ctx context.Context, serviceName string) func() {\n",{"type":34,"tag":91,"props":1553,"children":1554},{"class":93,"line":103},[1555],{"type":34,"tag":91,"props":1556,"children":1557},{},[1558],{"type":40,"value":1559},"    // OTLP exporter → Grafana Tempo / Jaeger / Azure Monitor\n",{"type":34,"tag":91,"props":1561,"children":1562},{"class":93,"line":112},[1563],{"type":34,"tag":91,"props":1564,"children":1565},{},[1566],{"type":40,"value":1567},"    exporter, _ := otlptracegrpc.New(ctx,\n",{"type":34,"tag":91,"props":1569,"children":1570},{"class":93,"line":121},[1571],{"type":34,"tag":91,"props":1572,"children":1573},{},[1574],{"type":40,"value":1575},"        otlptracegrpc.WithEndpoint(\"otel-collector:4317\"),\n",{"type":34,"tag":91,"props":1577,"children":1578},{"class":93,"line":131},[1579],{"type":34,"tag":91,"props":1580,"children":1581},{},[1582],{"type":40,"value":1583},"        otlptracegrpc.WithInsecure(),\n",{"type":34,"tag":91,"props":1585,"children":1586},{"class":93,"line":140},[1587],{"type":34,"tag":91,"props":1588,"children":1589},{},[1590],{"type":40,"value":981},{"type":34,"tag":91,"props":1592,"children":1593},{"class":93,"line":149},[1594],{"type":34,"tag":91,"props":1595,"children":1596},{"emptyLinePlaceholder":125},[1597],{"type":40,"value":128},{"type":34,"tag":91,"props":1599,"children":1600},{"class":93,"line":158},[1601],{"type":34,"tag":91,"props":1602,"children":1603},{},[1604],{"type":40,"value":1605},"    tp := sdktrace.NewTracerProvider(\n",{"type":34,"tag":91,"props":1607,"children":1608},{"class":93,"line":167},[1609],{"type":34,"tag":91,"props":1610,"children":1611},{},[1612],{"type":40,"value":1613},"        sdktrace.WithBatcher(exporter),\n",{"type":34,"tag":91,"props":1615,"children":1616},{"class":93,"line":176},[1617],{"type":34,"tag":91,"props":1618,"children":1619},{},[1620],{"type":40,"value":1621},"        sdktrace.WithResource(resource.NewWithAttributes(\n",{"type":34,"tag":91,"props":1623,"children":1624},{"class":93,"line":184},[1625],{"type":34,"tag":91,"props":1626,"children":1627},{},[1628],{"type":40,"value":1629},"            semconv.SchemaURL,\n",{"type":34,"tag":91,"props":1631,"children":1632},{"class":93,"line":193},[1633],{"type":34,"tag":91,"props":1634,"children":1635},{},[1636],{"type":40,"value":1637},"            semconv.ServiceName(serviceName),\n",{"type":34,"tag":91,"props":1639,"children":1640},{"class":93,"line":202},[1641],{"type":34,"tag":91,"props":1642,"children":1643},{},[1644],{"type":40,"value":1645},"            semconv.ServiceVersion(\"v2.4.1\"),\n",{"type":34,"tag":91,"props":1647,"children":1648},{"class":93,"line":210},[1649],{"type":34,"tag":91,"props":1650,"children":1651},{},[1652],{"type":40,"value":1653},"        )),\n",{"type":34,"tag":91,"props":1655,"children":1656},{"class":93,"line":218},[1657],{"type":34,"tag":91,"props":1658,"children":1659},{},[1660],{"type":40,"value":981},{"type":34,"tag":91,"props":1662,"children":1663},{"class":93,"line":227},[1664],{"type":34,"tag":91,"props":1665,"children":1666},{"emptyLinePlaceholder":125},[1667],{"type":40,"value":128},{"type":34,"tag":91,"props":1669,"children":1670},{"class":93,"line":236},[1671],{"type":34,"tag":91,"props":1672,"children":1673},{},[1674],{"type":40,"value":1675},"    otel.SetTracerProvider(tp)\n",{"type":34,"tag":91,"props":1677,"children":1678},{"class":93,"line":245},[1679],{"type":34,"tag":91,"props":1680,"children":1681},{},[1682],{"type":40,"value":1683},"    otel.SetTextMapPropagator(propagation.TraceContext{})\n",{"type":34,"tag":91,"props":1685,"children":1686},{"class":93,"line":254},[1687],{"type":34,"tag":91,"props":1688,"children":1689},{"emptyLinePlaceholder":125},[1690],{"type":40,"value":128},{"type":34,"tag":91,"props":1692,"children":1693},{"class":93,"line":262},[1694],{"type":34,"tag":91,"props":1695,"children":1696},{},[1697],{"type":40,"value":1698},"    // Prometheus metrics via grpc-go interceptors\n",{"type":34,"tag":91,"props":1700,"children":1701},{"class":93,"line":270},[1702],{"type":34,"tag":91,"props":1703,"children":1704},{},[1705],{"type":40,"value":1706},"    grpcmetrics.EnableHandlingTimeHistogram()\n",{"type":34,"tag":91,"props":1708,"children":1709},{"class":93,"line":279},[1710],{"type":34,"tag":91,"props":1711,"children":1712},{"emptyLinePlaceholder":125},[1713],{"type":40,"value":128},{"type":34,"tag":91,"props":1715,"children":1716},{"class":93,"line":288},[1717],{"type":34,"tag":91,"props":1718,"children":1719},{},[1720],{"type":40,"value":1721},"    return func() { tp.Shutdown(ctx) }\n",{"type":34,"tag":91,"props":1723,"children":1724},{"class":93,"line":297},[1725],{"type":34,"tag":91,"props":1726,"children":1727},{},[1728],{"type":40,"value":173},{"type":34,"tag":43,"props":1730,"children":1731},{},[1732,1734,1740],{"type":40,"value":1733},"Add structured logging with ",{"type":34,"tag":49,"props":1735,"children":1737},{"className":1736},[],[1738],{"type":40,"value":1739},"log/slog",{"type":40,"value":1741}," (standard library since Go 1.21) and you have a full observability stack without reaching for heavy third-party frameworks.",{"type":34,"tag":35,"props":1743,"children":1745},{"id":1744},"benchmarks-what-youre-getting",[1746],{"type":40,"value":1747},"Benchmarks: What You're Getting",{"type":34,"tag":43,"props":1749,"children":1750},{},[1751,1753,1759],{"type":40,"value":1752},"On a single ",{"type":34,"tag":49,"props":1754,"children":1756},{"className":1755},[],[1757],{"type":40,"value":1758},"c5.xlarge",{"type":40,"value":1760}," instance (4 vCPU, 8GB RAM), a Go/gRPC service comfortably handles:",{"type":34,"tag":1762,"props":1763,"children":1764},"ul",{},[1765,1777,1787,1797],{"type":34,"tag":1766,"props":1767,"children":1768},"li",{},[1769,1775],{"type":34,"tag":1770,"props":1771,"children":1772},"strong",{},[1773],{"type":40,"value":1774},"50,000+ requests/second",{"type":40,"value":1776}," for simple CRUD operations",{"type":34,"tag":1766,"props":1778,"children":1779},{},[1780,1785],{"type":34,"tag":1770,"props":1781,"children":1782},{},[1783],{"type":40,"value":1784},"p99 latency under 5ms",{"type":40,"value":1786}," with database connection pooling",{"type":34,"tag":1766,"props":1788,"children":1789},{},[1790,1795],{"type":34,"tag":1770,"props":1791,"children":1792},{},[1793],{"type":40,"value":1794},"~20MB RSS memory",{"type":40,"value":1796}," for the service process itself",{"type":34,"tag":1766,"props":1798,"children":1799},{},[1800,1805],{"type":34,"tag":1770,"props":1801,"children":1802},{},[1803],{"type":40,"value":1804},"\u003C10ms cold start",{"type":40,"value":1806}," in a containerised environment",{"type":34,"tag":43,"props":1808,"children":1809},{},[1810],{"type":40,"value":1811},"The equivalent Node.js/Express service with JSON typically achieves 8,000–12,000 requests/second at comparable p99 latency. The throughput difference comes almost entirely from Protobuf serialisation overhead reduction and Go's efficient scheduler.",{"type":34,"tag":43,"props":1813,"children":1814},{},[1815],{"type":40,"value":1816},"gRPC's streaming support also unlocks patterns JSON REST simply can't match efficiently — real-time product availability updates via server push, bidirectional chat, and large data exports without buffering entire result sets in memory.",{"type":34,"tag":43,"props":1818,"children":1819},{},[1820],{"type":40,"value":1821},"Build the service once with the right foundation, and you'll rarely need to revisit it for performance reasons.",{"type":34,"tag":1823,"props":1824,"children":1825},"style",{},[1826],{"type":40,"value":1827},"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);}",{"title":7,"searchDepth":112,"depth":112,"links":1829},[1830,1831,1832,1833,1834,1835,1836],{"id":37,"depth":103,"text":41},{"id":64,"depth":103,"text":67},{"id":371,"depth":103,"text":374},{"id":1065,"depth":103,"text":1068},{"id":1358,"depth":103,"text":1361},{"id":1528,"depth":103,"text":1531},{"id":1744,"depth":103,"text":1747},"markdown","content:blog:golang-grpc-microservices.md","content","blog/golang-grpc-microservices.md","blog/golang-grpc-microservices","md",[1844,2507,4624],{"_path":1845,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":1846,"description":1847,"slug":1848,"date":1849,"readTime":1850,"category":1851,"image":1852,"imageCaption":1853,"author":1854,"tags":1856,"body":1861,"_type":1837,"_id":2504,"_source":1839,"_file":2505,"_stem":2506,"_extension":1842},"/blog/azure-architecture-patterns","Scalable Azure Architecture Patterns Every Cloud Engineer Should Know in 2025","Explore the proven Azure architecture patterns—from Container Apps microservices to multi-region high availability—that MediaFront uses to build resilient, cost-efficient cloud applications.","azure-architecture-patterns","2025-04-10","10 min","Cloud","https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=1200&h=600&fit=crop&auto=format","Azure cloud infrastructure supporting modern microservices at global scale",{"name":17,"role":18,"avatar":19,"bio":20,"social":1855},{"github":22,"twitter":23,"linkedin":24},[1857,1858,28,1859,1860],"Azure","Cloud Architecture","Containers","DevOps",{"type":31,"children":1862,"toc":2493},[1863,1869,1874,1880,1885,1890,1933,1938,1946,1951,1957,1962,1967,2063,2068,2074,2079,2112,2117,2123,2128,2181,2186,2192,2197,2205,2210,2216,2221,2264,2270,2275,2417,2430,2436,2441,2484,2489],{"type":34,"tag":35,"props":1864,"children":1866},{"id":1865},"why-azure-architecture-decisions-matter-more-than-ever",[1867],{"type":40,"value":1868},"Why Azure Architecture Decisions Matter More Than Ever",{"type":34,"tag":43,"props":1870,"children":1871},{},[1872],{"type":40,"value":1873},"Choosing the wrong architecture pattern on Azure can cost a company thousands of euros per month in wasted compute and dozens of engineering hours untangling bottlenecks. Choose well, and you get an application that scales automatically, stays resilient under pressure, and grows with your business. This guide covers the five patterns we deploy most frequently at MediaFront and why each one earns its place in a modern cloud stack.",{"type":34,"tag":35,"props":1875,"children":1877},{"id":1876},"microservices-with-azure-container-apps",[1878],{"type":40,"value":1879},"Microservices with Azure Container Apps",{"type":34,"tag":43,"props":1881,"children":1882},{},[1883],{"type":40,"value":1884},"Azure Container Apps is the sweet spot between the simplicity of App Service and the raw power of AKS. It runs your containers on a serverless runtime, so you pay only for what you use while gaining all the benefits of orchestration.",{"type":34,"tag":43,"props":1886,"children":1887},{},[1888],{"type":40,"value":1889},"Key capabilities that matter in production:",{"type":34,"tag":1762,"props":1891,"children":1892},{},[1893,1903,1913,1923],{"type":34,"tag":1766,"props":1894,"children":1895},{},[1896,1901],{"type":34,"tag":1770,"props":1897,"children":1898},{},[1899],{"type":40,"value":1900},"HTTP and event-driven scaling",{"type":40,"value":1902}," — scale a service to zero when idle, spike to hundreds of replicas during peak load without a single YAML manifest change",{"type":34,"tag":1766,"props":1904,"children":1905},{},[1906,1911],{"type":34,"tag":1770,"props":1907,"children":1908},{},[1909],{"type":40,"value":1910},"Revision management",{"type":40,"value":1912}," — deploy a new version, split traffic 90/10 between old and new, then cut over once telemetry confirms stability",{"type":34,"tag":1766,"props":1914,"children":1915},{},[1916,1921],{"type":34,"tag":1770,"props":1917,"children":1918},{},[1919],{"type":40,"value":1920},"Built-in service-to-service communication",{"type":40,"value":1922}," via Dapr sidecars, removing the networking boilerplate you'd otherwise write by hand",{"type":34,"tag":1766,"props":1924,"children":1925},{},[1926,1931],{"type":34,"tag":1770,"props":1927,"children":1928},{},[1929],{"type":40,"value":1930},"gRPC and WebSocket support",{"type":40,"value":1932}," — not just REST",{"type":34,"tag":43,"props":1934,"children":1935},{},[1936],{"type":40,"value":1937},"A typical three-tier architecture we ship looks like this:",{"type":34,"tag":81,"props":1939,"children":1941},{"code":1940},"Azure API Management\n  ├── Auth Service        (Container App — scales to 0 at night)\n  ├── Catalogue Service   (Container App — scales 1–20 replicas)\n  │     └── Azure Cosmos DB (multi-region writes)\n  ├── Order Service       (Container App)\n  │     └── Azure SQL     (zone-redundant)\n  └── Notification Service (Container App)\n        └── Azure Service Bus (Standard tier)\n",[1942],{"type":34,"tag":49,"props":1943,"children":1944},{"__ignoreMap":7},[1945],{"type":40,"value":1940},{"type":34,"tag":43,"props":1947,"children":1948},{},[1949],{"type":40,"value":1950},"Each service owns its data store and communicates through well-defined contracts. Teams can deploy independently, and a failure in the Notification Service never cascades into the Order Service.",{"type":34,"tag":35,"props":1952,"children":1954},{"id":1953},"event-driven-architecture-with-event-grid-and-functions",[1955],{"type":40,"value":1956},"Event-Driven Architecture with Event Grid and Functions",{"type":34,"tag":43,"props":1958,"children":1959},{},[1960],{"type":40,"value":1961},"When your system needs to react to things that happen — a file upload, a payment completing, a sensor reading arriving — an event-driven backbone beats tight REST coupling every time.",{"type":34,"tag":43,"props":1963,"children":1964},{},[1965],{"type":40,"value":1966},"Azure gives you three complementary messaging primitives:",{"type":34,"tag":1968,"props":1969,"children":1970},"table",{},[1971,1995],{"type":34,"tag":1972,"props":1973,"children":1974},"thead",{},[1975],{"type":34,"tag":1976,"props":1977,"children":1978},"tr",{},[1979,1985,1990],{"type":34,"tag":1980,"props":1981,"children":1982},"th",{},[1983],{"type":40,"value":1984},"Service",{"type":34,"tag":1980,"props":1986,"children":1987},{},[1988],{"type":40,"value":1989},"Best For",{"type":34,"tag":1980,"props":1991,"children":1992},{},[1993],{"type":40,"value":1994},"Throughput",{"type":34,"tag":1996,"props":1997,"children":1998},"tbody",{},[1999,2021,2042],{"type":34,"tag":1976,"props":2000,"children":2001},{},[2002,2011,2016],{"type":34,"tag":2003,"props":2004,"children":2005},"td",{},[2006],{"type":34,"tag":1770,"props":2007,"children":2008},{},[2009],{"type":40,"value":2010},"Event Grid",{"type":34,"tag":2003,"props":2012,"children":2013},{},[2014],{"type":40,"value":2015},"Reactive routing of discrete events",{"type":34,"tag":2003,"props":2017,"children":2018},{},[2019],{"type":40,"value":2020},"Millions/sec",{"type":34,"tag":1976,"props":2022,"children":2023},{},[2024,2032,2037],{"type":34,"tag":2003,"props":2025,"children":2026},{},[2027],{"type":34,"tag":1770,"props":2028,"children":2029},{},[2030],{"type":40,"value":2031},"Event Hubs",{"type":34,"tag":2003,"props":2033,"children":2034},{},[2035],{"type":40,"value":2036},"High-volume data streaming and ingestion",{"type":34,"tag":2003,"props":2038,"children":2039},{},[2040],{"type":40,"value":2041},"Petabyte-scale",{"type":34,"tag":1976,"props":2043,"children":2044},{},[2045,2053,2058],{"type":34,"tag":2003,"props":2046,"children":2047},{},[2048],{"type":34,"tag":1770,"props":2049,"children":2050},{},[2051],{"type":40,"value":2052},"Service Bus",{"type":34,"tag":2003,"props":2054,"children":2055},{},[2056],{"type":40,"value":2057},"Reliable ordered message delivery",{"type":34,"tag":2003,"props":2059,"children":2060},{},[2061],{"type":40,"value":2062},"Enterprise-grade",{"type":34,"tag":43,"props":2064,"children":2065},{},[2066],{"type":40,"value":2067},"The pattern we reach for most: Event Grid as the central event router, Service Bus queues for per-service processing, and Azure Functions as lightweight consumers. The result is a system where adding a new feature means wiring up a new Function—not modifying existing services.",{"type":34,"tag":35,"props":2069,"children":2071},{"id":2070},"global-static-web-apps-edge-functions",[2072],{"type":40,"value":2073},"Global Static Web Apps + Edge Functions",{"type":34,"tag":43,"props":2075,"children":2076},{},[2077],{"type":40,"value":2078},"For marketing sites, SaaS dashboards, and content-heavy applications, the combination of Azure Static Web Apps with Azure Functions delivers exceptional performance at minimal cost:",{"type":34,"tag":1762,"props":2080,"children":2081},{},[2082,2092,2102],{"type":34,"tag":1766,"props":2083,"children":2084},{},[2085,2090],{"type":34,"tag":1770,"props":2086,"children":2087},{},[2088],{"type":40,"value":2089},"Static Web Apps",{"type":40,"value":2091}," serve pre-rendered HTML, CSS, and JS from Azure's global CDN — Lighthouse scores of 95+ become routine",{"type":34,"tag":1766,"props":2093,"children":2094},{},[2095,2100],{"type":34,"tag":1770,"props":2096,"children":2097},{},[2098],{"type":40,"value":2099},"Integrated API",{"type":40,"value":2101}," routes live alongside your frontend in the same repository; Azure handles routing automatically",{"type":34,"tag":1766,"props":2103,"children":2104},{},[2105,2110],{"type":34,"tag":1770,"props":2106,"children":2107},{},[2108],{"type":40,"value":2109},"Azure Front Door",{"type":40,"value":2111}," sits in front as a global entry point, providing WAF, DDoS protection, and sub-10ms SSL termination",{"type":34,"tag":43,"props":2113,"children":2114},{},[2115],{"type":40,"value":2116},"When workloads outgrow Functions, we migrate the API layer to Azure Container Apps without touching the frontend infrastructure.",{"type":34,"tag":35,"props":2118,"children":2120},{"id":2119},"multi-region-high-availability",[2121],{"type":40,"value":2122},"Multi-Region High Availability",{"type":34,"tag":43,"props":2124,"children":2125},{},[2126],{"type":40,"value":2127},"For clients with SLA commitments above 99.9%, a single-region deployment simply isn't enough. Our multi-region blueprint:",{"type":34,"tag":2129,"props":2130,"children":2131},"ol",{},[2132,2141,2151,2161,2171],{"type":34,"tag":1766,"props":2133,"children":2134},{},[2135,2139],{"type":34,"tag":1770,"props":2136,"children":2137},{},[2138],{"type":40,"value":2109},{"type":40,"value":2140}," routes users to the closest healthy region via anycast",{"type":34,"tag":1766,"props":2142,"children":2143},{},[2144,2149],{"type":34,"tag":1770,"props":2145,"children":2146},{},[2147],{"type":40,"value":2148},"Identical application stacks",{"type":40,"value":2150}," in at least two Azure regions (paired regions where possible)",{"type":34,"tag":1766,"props":2152,"children":2153},{},[2154,2159],{"type":34,"tag":1770,"props":2155,"children":2156},{},[2157],{"type":40,"value":2158},"Cosmos DB multi-region writes",{"type":40,"value":2160}," — data is always written to the user's nearest region",{"type":34,"tag":1766,"props":2162,"children":2163},{},[2164,2169],{"type":34,"tag":1770,"props":2165,"children":2166},{},[2167],{"type":40,"value":2168},"Azure SQL Geo-Replication",{"type":40,"value":2170}," for relational workloads that need ACID guarantees",{"type":34,"tag":1766,"props":2172,"children":2173},{},[2174,2179],{"type":34,"tag":1770,"props":2175,"children":2176},{},[2177],{"type":40,"value":2178},"Regular chaos engineering",{"type":40,"value":2180}," — we inject failures in staging to prove the failover actually works",{"type":34,"tag":43,"props":2182,"children":2183},{},[2184],{"type":40,"value":2185},"Active-active for stateless services, active-passive with fast failover for stateful ones. The distinction matters: active-active everywhere sounds great until you need to reconcile conflicting writes.",{"type":34,"tag":35,"props":2187,"children":2189},{"id":2188},"cost-effective-data-processing-with-data-factory-and-synapse",[2190],{"type":40,"value":2191},"Cost-Effective Data Processing with Data Factory and Synapse",{"type":34,"tag":43,"props":2193,"children":2194},{},[2195],{"type":40,"value":2196},"Analytics pipelines don't need to run on expensive always-on compute. Our serverless data architecture:",{"type":34,"tag":81,"props":2198,"children":2200},{"code":2199},"Raw Data Sources → Azure Data Factory (orchestration)\n                       ↓\n                 Azure Blob Storage (cold storage, \u003C €0.02/GB)\n                       ↓\n              Azure Synapse Serverless SQL (query on demand)\n                       ↓\n                    Power BI (embedded reports)\n",[2201],{"type":34,"tag":49,"props":2202,"children":2203},{"__ignoreMap":7},[2204],{"type":40,"value":2199},{"type":34,"tag":43,"props":2206,"children":2207},{},[2208],{"type":40,"value":2209},"Data Factory handles scheduling and movement. Synapse runs complex queries against Parquet files without a warehouse to provision. Power BI surfaces the results to stakeholders. The entire stack scales from zero and costs a fraction of a dedicated data warehouse for most SME use cases.",{"type":34,"tag":35,"props":2211,"children":2213},{"id":2212},"security-zero-trust-from-day-one",[2214],{"type":40,"value":2215},"Security: Zero-Trust from Day One",{"type":34,"tag":43,"props":2217,"children":2218},{},[2219],{"type":40,"value":2220},"Across every architecture pattern above, we apply the same security baseline:",{"type":34,"tag":1762,"props":2222,"children":2223},{},[2224,2234,2244,2254],{"type":34,"tag":1766,"props":2225,"children":2226},{},[2227,2232],{"type":34,"tag":1770,"props":2228,"children":2229},{},[2230],{"type":40,"value":2231},"Managed Identities",{"type":40,"value":2233}," everywhere — no secrets stored in environment variables or Key Vault references in app settings that could be read by anyone with Contributor access",{"type":34,"tag":1766,"props":2235,"children":2236},{},[2237,2242],{"type":34,"tag":1770,"props":2238,"children":2239},{},[2240],{"type":40,"value":2241},"Private Endpoints",{"type":40,"value":2243}," for all PaaS services — your Cosmos DB, Service Bus, and Storage accounts should never be reachable from the public internet",{"type":34,"tag":1766,"props":2245,"children":2246},{},[2247,2252],{"type":34,"tag":1770,"props":2248,"children":2249},{},[2250],{"type":40,"value":2251},"Azure Defender for Cloud",{"type":40,"value":2253}," continuously scanning for misconfiguration",{"type":34,"tag":1766,"props":2255,"children":2256},{},[2257,2262],{"type":34,"tag":1770,"props":2258,"children":2259},{},[2260],{"type":40,"value":2261},"Key Vault references",{"type":40,"value":2263}," in App Configuration so secrets rotate without redeployment",{"type":34,"tag":35,"props":2265,"children":2267},{"id":2266},"infrastructure-as-code-azure-bicep",[2268],{"type":40,"value":2269},"Infrastructure as Code: Azure Bicep",{"type":34,"tag":43,"props":2271,"children":2272},{},[2273],{"type":40,"value":2274},"Every pattern above is deployed through code, not the portal. We use Azure Bicep for its native Azure integration and superior readability compared to ARM templates:",{"type":34,"tag":81,"props":2276,"children":2280},{"code":2277,"language":2278,"meta":7,"className":2279,"style":7},"resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {\n  name: 'order-service'\n  location: location\n  properties: {\n    configuration: {\n      ingress: { external: false, targetPort: 8080 }\n    }\n    template: {\n      containers: [{\n        name: 'order-service'\n        image: '${acr.name}.azurecr.io/order-service:${imageTag}'\n        resources: { cpu: '0.5', memory: '1Gi' }\n      }]\n      scale: { minReplicas: 1, maxReplicas: 20 }\n    }\n  }\n}\n","bicep","language-bicep shiki shiki-themes github-light",[2281],{"type":34,"tag":49,"props":2282,"children":2283},{"__ignoreMap":7},[2284,2292,2300,2308,2316,2324,2332,2339,2347,2355,2363,2371,2379,2387,2395,2402,2410],{"type":34,"tag":91,"props":2285,"children":2286},{"class":93,"line":94},[2287],{"type":34,"tag":91,"props":2288,"children":2289},{},[2290],{"type":40,"value":2291},"resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {\n",{"type":34,"tag":91,"props":2293,"children":2294},{"class":93,"line":103},[2295],{"type":34,"tag":91,"props":2296,"children":2297},{},[2298],{"type":40,"value":2299},"  name: 'order-service'\n",{"type":34,"tag":91,"props":2301,"children":2302},{"class":93,"line":112},[2303],{"type":34,"tag":91,"props":2304,"children":2305},{},[2306],{"type":40,"value":2307},"  location: location\n",{"type":34,"tag":91,"props":2309,"children":2310},{"class":93,"line":121},[2311],{"type":34,"tag":91,"props":2312,"children":2313},{},[2314],{"type":40,"value":2315},"  properties: {\n",{"type":34,"tag":91,"props":2317,"children":2318},{"class":93,"line":131},[2319],{"type":34,"tag":91,"props":2320,"children":2321},{},[2322],{"type":40,"value":2323},"    configuration: {\n",{"type":34,"tag":91,"props":2325,"children":2326},{"class":93,"line":140},[2327],{"type":34,"tag":91,"props":2328,"children":2329},{},[2330],{"type":40,"value":2331},"      ingress: { external: false, targetPort: 8080 }\n",{"type":34,"tag":91,"props":2333,"children":2334},{"class":93,"line":149},[2335],{"type":34,"tag":91,"props":2336,"children":2337},{},[2338],{"type":40,"value":578},{"type":34,"tag":91,"props":2340,"children":2341},{"class":93,"line":158},[2342],{"type":34,"tag":91,"props":2343,"children":2344},{},[2345],{"type":40,"value":2346},"    template: {\n",{"type":34,"tag":91,"props":2348,"children":2349},{"class":93,"line":167},[2350],{"type":34,"tag":91,"props":2351,"children":2352},{},[2353],{"type":40,"value":2354},"      containers: [{\n",{"type":34,"tag":91,"props":2356,"children":2357},{"class":93,"line":176},[2358],{"type":34,"tag":91,"props":2359,"children":2360},{},[2361],{"type":40,"value":2362},"        name: 'order-service'\n",{"type":34,"tag":91,"props":2364,"children":2365},{"class":93,"line":184},[2366],{"type":34,"tag":91,"props":2367,"children":2368},{},[2369],{"type":40,"value":2370},"        image: '${acr.name}.azurecr.io/order-service:${imageTag}'\n",{"type":34,"tag":91,"props":2372,"children":2373},{"class":93,"line":193},[2374],{"type":34,"tag":91,"props":2375,"children":2376},{},[2377],{"type":40,"value":2378},"        resources: { cpu: '0.5', memory: '1Gi' }\n",{"type":34,"tag":91,"props":2380,"children":2381},{"class":93,"line":202},[2382],{"type":34,"tag":91,"props":2383,"children":2384},{},[2385],{"type":40,"value":2386},"      }]\n",{"type":34,"tag":91,"props":2388,"children":2389},{"class":93,"line":210},[2390],{"type":34,"tag":91,"props":2391,"children":2392},{},[2393],{"type":40,"value":2394},"      scale: { minReplicas: 1, maxReplicas: 20 }\n",{"type":34,"tag":91,"props":2396,"children":2397},{"class":93,"line":218},[2398],{"type":34,"tag":91,"props":2399,"children":2400},{},[2401],{"type":40,"value":578},{"type":34,"tag":91,"props":2403,"children":2404},{"class":93,"line":227},[2405],{"type":34,"tag":91,"props":2406,"children":2407},{},[2408],{"type":40,"value":2409},"  }\n",{"type":34,"tag":91,"props":2411,"children":2412},{"class":93,"line":236},[2413],{"type":34,"tag":91,"props":2414,"children":2415},{},[2416],{"type":40,"value":173},{"type":34,"tag":43,"props":2418,"children":2419},{},[2420,2422,2428],{"type":40,"value":2421},"Version-controlled infrastructure means every environment is reproducible, every change is auditable, and rollbacks are a ",{"type":34,"tag":49,"props":2423,"children":2425},{"className":2424},[],[2426],{"type":40,"value":2427},"git revert",{"type":40,"value":2429}," away.",{"type":34,"tag":35,"props":2431,"children":2433},{"id":2432},"choosing-the-right-pattern",[2434],{"type":40,"value":2435},"Choosing the Right Pattern",{"type":34,"tag":43,"props":2437,"children":2438},{},[2439],{"type":40,"value":2440},"No single pattern fits every project. Use this as a quick guide:",{"type":34,"tag":1762,"props":2442,"children":2443},{},[2444,2454,2464,2474],{"type":34,"tag":1766,"props":2445,"children":2446},{},[2447,2452],{"type":34,"tag":1770,"props":2448,"children":2449},{},[2450],{"type":40,"value":2451},"Greenfield SaaS product",{"type":40,"value":2453},": Container Apps + Event Grid + Cosmos DB",{"type":34,"tag":1766,"props":2455,"children":2456},{},[2457,2462],{"type":34,"tag":1770,"props":2458,"children":2459},{},[2460],{"type":40,"value":2461},"Marketing site with dynamic API",{"type":40,"value":2463},": Static Web Apps + Functions + Azure SQL",{"type":34,"tag":1766,"props":2465,"children":2466},{},[2467,2472],{"type":34,"tag":1770,"props":2468,"children":2469},{},[2470],{"type":40,"value":2471},"Mission-critical transactional system",{"type":40,"value":2473},": Multi-region + Service Bus + SQL Geo-Replication",{"type":34,"tag":1766,"props":2475,"children":2476},{},[2477,2482],{"type":34,"tag":1770,"props":2478,"children":2479},{},[2480],{"type":40,"value":2481},"Analytics-heavy application",{"type":40,"value":2483},": Data Factory + Synapse Serverless + Power BI",{"type":34,"tag":43,"props":2485,"children":2486},{},[2487],{"type":40,"value":2488},"The best Azure architecture is the one that matches your load profile, your team's operational maturity, and your cost envelope — not the most sophisticated one you can build.",{"type":34,"tag":1823,"props":2490,"children":2491},{},[2492],{"type":40,"value":1827},{"title":7,"searchDepth":112,"depth":112,"links":2494},[2495,2496,2497,2498,2499,2500,2501,2502,2503],{"id":1865,"depth":103,"text":1868},{"id":1876,"depth":103,"text":1879},{"id":1953,"depth":103,"text":1956},{"id":2070,"depth":103,"text":2073},{"id":2119,"depth":103,"text":2122},{"id":2188,"depth":103,"text":2191},{"id":2212,"depth":103,"text":2215},{"id":2266,"depth":103,"text":2269},{"id":2432,"depth":103,"text":2435},"content:blog:azure-architecture-patterns.md","blog/azure-architecture-patterns.md","blog/azure-architecture-patterns",{"_path":2508,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":2509,"description":2510,"slug":2511,"date":2512,"readTime":12,"category":1860,"image":2513,"imageCaption":2514,"author":2515,"tags":2517,"body":2521,"_type":1837,"_id":4621,"_source":1839,"_file":4622,"_stem":4623,"_extension":1842},"/blog/containerization-guide","Docker & Kubernetes: A Complete Containerization Guide for Production-Ready Apps","From writing your first Dockerfile to orchestrating workloads with Kubernetes—a practical containerization guide covering image optimisation, security, and a real-world case study that cut deployment time from hours to minutes.","containerization-guide","2025-03-28","https://images.unsplash.com/photo-1605745341112-85968b19335b?w=1200&h=600&fit=crop&auto=format","Container infrastructure running microservices in a production Kubernetes cluster",{"name":17,"role":18,"avatar":19,"bio":20,"social":2516},{"github":22,"twitter":23,"linkedin":24},[2518,2519,1859,1860,2520],"Docker","Kubernetes","Cloud Native",{"type":31,"children":2522,"toc":4606},[2523,2529,2550,2555,2561,2566,2609,2614,2620,2625,2632,2637,2787,2793,2798,2881,3006,3012,3017,3580,3601,3607,3612,3618,3719,3725,4412,4433,4439,4444,4543,4548,4554,4559,4592,4597,4602],{"type":34,"tag":35,"props":2524,"children":2526},{"id":2525},"the-promise-and-the-reality-of-containerisation",[2527],{"type":40,"value":2528},"The Promise (and the Reality) of Containerisation",{"type":34,"tag":43,"props":2530,"children":2531},{},[2532,2534,2540,2542,2548],{"type":40,"value":2533},"Containers solve a problem every developer knows well: ",{"type":34,"tag":2535,"props":2536,"children":2537},"em",{},[2538],{"type":40,"value":2539},"\"it works on my machine.\"",{"type":40,"value":2541}," By packaging an application alongside all its runtime dependencies into a portable, reproducible unit, containers eliminate the friction between development, staging, and production environments. But getting from a working Dockerfile to a resilient, production-ready container strategy requires more than just running ",{"type":34,"tag":49,"props":2543,"children":2545},{"className":2544},[],[2546],{"type":40,"value":2547},"docker build",{"type":40,"value":2549},".",{"type":34,"tag":43,"props":2551,"children":2552},{},[2553],{"type":40,"value":2554},"This guide walks through the full journey—from container fundamentals to Kubernetes orchestration—drawing on patterns we've refined across dozens of client projects at MediaFront.",{"type":34,"tag":35,"props":2556,"children":2558},{"id":2557},"what-containers-actually-are",[2559],{"type":40,"value":2560},"What Containers Actually Are",{"type":34,"tag":43,"props":2562,"children":2563},{},[2564],{"type":40,"value":2565},"Unlike virtual machines, containers don't virtualise hardware. They share the host operating system kernel while running in isolated user-space processes. The practical result:",{"type":34,"tag":1762,"props":2567,"children":2568},{},[2569,2579,2589,2599],{"type":34,"tag":1766,"props":2570,"children":2571},{},[2572,2577],{"type":34,"tag":1770,"props":2573,"children":2574},{},[2575],{"type":40,"value":2576},"Startup in milliseconds",{"type":40,"value":2578},", not minutes",{"type":34,"tag":1766,"props":2580,"children":2581},{},[2582,2587],{"type":34,"tag":1770,"props":2583,"children":2584},{},[2585],{"type":40,"value":2586},"Image sizes in megabytes",{"type":40,"value":2588},", not gigabytes",{"type":34,"tag":1766,"props":2590,"children":2591},{},[2592,2597],{"type":34,"tag":1770,"props":2593,"children":2594},{},[2595],{"type":40,"value":2596},"Predictable resource usage",{"type":40,"value":2598}," — you can set hard CPU and memory limits",{"type":34,"tag":1766,"props":2600,"children":2601},{},[2602,2607],{"type":34,"tag":1770,"props":2603,"children":2604},{},[2605],{"type":40,"value":2606},"Immutable deployments",{"type":40,"value":2608}," — every release is a new image tag, making rollbacks trivial",{"type":34,"tag":43,"props":2610,"children":2611},{},[2612],{"type":40,"value":2613},"The trade-off: containers on the same host share the kernel, which has security implications we'll address below.",{"type":34,"tag":35,"props":2615,"children":2617},{"id":2616},"writing-production-grade-dockerfiles",[2618],{"type":40,"value":2619},"Writing Production-Grade Dockerfiles",{"type":34,"tag":43,"props":2621,"children":2622},{},[2623],{"type":40,"value":2624},"A Dockerfile is infrastructure as code for your runtime environment. Small choices here have outsized consequences in production.",{"type":34,"tag":2626,"props":2627,"children":2629},"h3",{"id":2628},"use-multi-stage-builds",[2630],{"type":40,"value":2631},"Use Multi-Stage Builds",{"type":34,"tag":43,"props":2633,"children":2634},{},[2635],{"type":40,"value":2636},"Multi-stage builds separate the build toolchain from the runtime image, dramatically reducing final image size and attack surface:",{"type":34,"tag":81,"props":2638,"children":2642},{"className":2639,"code":2640,"language":2641,"meta":7,"style":7},"language-dockerfile shiki shiki-themes github-light","# Stage 1: Build\nFROM mcr.microsoft.com/dotnet/sdk:8.0 AS build\nWORKDIR /src\nCOPY [\"OrderService.csproj\", \"./\"]\nRUN dotnet restore\nCOPY . .\nRUN dotnet publish -c Release -o /app/publish\n\n# Stage 2: Runtime-only image (~100MB vs ~800MB SDK image)\nFROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime\nWORKDIR /app\nEXPOSE 8080\nCOPY --from=build /app/publish .\n\n# Never run as root in production\nUSER app\n\nENTRYPOINT [\"dotnet\", \"OrderService.dll\"]\n","dockerfile",[2643],{"type":34,"tag":49,"props":2644,"children":2645},{"__ignoreMap":7},[2646,2654,2662,2670,2678,2686,2694,2702,2709,2717,2725,2733,2741,2749,2756,2764,2772,2779],{"type":34,"tag":91,"props":2647,"children":2648},{"class":93,"line":94},[2649],{"type":34,"tag":91,"props":2650,"children":2651},{},[2652],{"type":40,"value":2653},"# Stage 1: Build\n",{"type":34,"tag":91,"props":2655,"children":2656},{"class":93,"line":103},[2657],{"type":34,"tag":91,"props":2658,"children":2659},{},[2660],{"type":40,"value":2661},"FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build\n",{"type":34,"tag":91,"props":2663,"children":2664},{"class":93,"line":112},[2665],{"type":34,"tag":91,"props":2666,"children":2667},{},[2668],{"type":40,"value":2669},"WORKDIR /src\n",{"type":34,"tag":91,"props":2671,"children":2672},{"class":93,"line":121},[2673],{"type":34,"tag":91,"props":2674,"children":2675},{},[2676],{"type":40,"value":2677},"COPY [\"OrderService.csproj\", \"./\"]\n",{"type":34,"tag":91,"props":2679,"children":2680},{"class":93,"line":131},[2681],{"type":34,"tag":91,"props":2682,"children":2683},{},[2684],{"type":40,"value":2685},"RUN dotnet restore\n",{"type":34,"tag":91,"props":2687,"children":2688},{"class":93,"line":140},[2689],{"type":34,"tag":91,"props":2690,"children":2691},{},[2692],{"type":40,"value":2693},"COPY . .\n",{"type":34,"tag":91,"props":2695,"children":2696},{"class":93,"line":149},[2697],{"type":34,"tag":91,"props":2698,"children":2699},{},[2700],{"type":40,"value":2701},"RUN dotnet publish -c Release -o /app/publish\n",{"type":34,"tag":91,"props":2703,"children":2704},{"class":93,"line":158},[2705],{"type":34,"tag":91,"props":2706,"children":2707},{"emptyLinePlaceholder":125},[2708],{"type":40,"value":128},{"type":34,"tag":91,"props":2710,"children":2711},{"class":93,"line":167},[2712],{"type":34,"tag":91,"props":2713,"children":2714},{},[2715],{"type":40,"value":2716},"# Stage 2: Runtime-only image (~100MB vs ~800MB SDK image)\n",{"type":34,"tag":91,"props":2718,"children":2719},{"class":93,"line":176},[2720],{"type":34,"tag":91,"props":2721,"children":2722},{},[2723],{"type":40,"value":2724},"FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime\n",{"type":34,"tag":91,"props":2726,"children":2727},{"class":93,"line":184},[2728],{"type":34,"tag":91,"props":2729,"children":2730},{},[2731],{"type":40,"value":2732},"WORKDIR /app\n",{"type":34,"tag":91,"props":2734,"children":2735},{"class":93,"line":193},[2736],{"type":34,"tag":91,"props":2737,"children":2738},{},[2739],{"type":40,"value":2740},"EXPOSE 8080\n",{"type":34,"tag":91,"props":2742,"children":2743},{"class":93,"line":202},[2744],{"type":34,"tag":91,"props":2745,"children":2746},{},[2747],{"type":40,"value":2748},"COPY --from=build /app/publish .\n",{"type":34,"tag":91,"props":2750,"children":2751},{"class":93,"line":210},[2752],{"type":34,"tag":91,"props":2753,"children":2754},{"emptyLinePlaceholder":125},[2755],{"type":40,"value":128},{"type":34,"tag":91,"props":2757,"children":2758},{"class":93,"line":218},[2759],{"type":34,"tag":91,"props":2760,"children":2761},{},[2762],{"type":40,"value":2763},"# Never run as root in production\n",{"type":34,"tag":91,"props":2765,"children":2766},{"class":93,"line":227},[2767],{"type":34,"tag":91,"props":2768,"children":2769},{},[2770],{"type":40,"value":2771},"USER app\n",{"type":34,"tag":91,"props":2773,"children":2774},{"class":93,"line":236},[2775],{"type":34,"tag":91,"props":2776,"children":2777},{"emptyLinePlaceholder":125},[2778],{"type":40,"value":128},{"type":34,"tag":91,"props":2780,"children":2781},{"class":93,"line":245},[2782],{"type":34,"tag":91,"props":2783,"children":2784},{},[2785],{"type":40,"value":2786},"ENTRYPOINT [\"dotnet\", \"OrderService.dll\"]\n",{"type":34,"tag":2626,"props":2788,"children":2790},{"id":2789},"security-hardening-checklist",[2791],{"type":40,"value":2792},"Security Hardening Checklist",{"type":34,"tag":43,"props":2794,"children":2795},{},[2796],{"type":40,"value":2797},"Before any image goes to production, verify:",{"type":34,"tag":1762,"props":2799,"children":2800},{},[2801,2819,2829,2845,2871],{"type":34,"tag":1766,"props":2802,"children":2803},{},[2804,2809,2811,2817],{"type":34,"tag":1770,"props":2805,"children":2806},{},[2807],{"type":40,"value":2808},"Non-root user",{"type":40,"value":2810}," — add ",{"type":34,"tag":49,"props":2812,"children":2814},{"className":2813},[],[2815],{"type":40,"value":2816},"USER app",{"type":40,"value":2818}," (or create a dedicated user) so a compromised container doesn't have root access to the host",{"type":34,"tag":1766,"props":2820,"children":2821},{},[2822,2827],{"type":34,"tag":1770,"props":2823,"children":2824},{},[2825],{"type":40,"value":2826},"Read-only filesystem",{"type":40,"value":2828}," — mount volumes only where writes are genuinely needed",{"type":34,"tag":1766,"props":2830,"children":2831},{},[2832,2837,2839],{"type":34,"tag":1770,"props":2833,"children":2834},{},[2835],{"type":40,"value":2836},"No secrets in image layers",{"type":40,"value":2838}," — use build secrets or runtime environment injection, never ",{"type":34,"tag":49,"props":2840,"children":2842},{"className":2841},[],[2843],{"type":40,"value":2844},"COPY .env .",{"type":34,"tag":1766,"props":2846,"children":2847},{},[2848,2853,2855,2861,2863,2869],{"type":34,"tag":1770,"props":2849,"children":2850},{},[2851],{"type":40,"value":2852},"Pinned base image tags",{"type":40,"value":2854}," — ",{"type":34,"tag":49,"props":2856,"children":2858},{"className":2857},[],[2859],{"type":40,"value":2860},"FROM node:20.14.0-alpine3.20",{"type":40,"value":2862}," is reproducible; ",{"type":34,"tag":49,"props":2864,"children":2866},{"className":2865},[],[2867],{"type":40,"value":2868},"FROM node:latest",{"type":40,"value":2870}," is a reliability hazard",{"type":34,"tag":1766,"props":2872,"children":2873},{},[2874,2879],{"type":34,"tag":1770,"props":2875,"children":2876},{},[2877],{"type":40,"value":2878},"Vulnerability scanning",{"type":40,"value":2880}," — integrate Trivy or Grype into your CI pipeline; fail the build on HIGH or CRITICAL findings",{"type":34,"tag":81,"props":2882,"children":2886},{"className":2883,"code":2884,"language":2885,"meta":7,"style":7},"language-yaml shiki shiki-themes github-light","# GitHub Actions step — fails PR if critical CVEs found\n- name: Scan image for vulnerabilities\n  uses: aquasecurity/trivy-action@master\n  with:\n    image-ref: ${{ env.IMAGE }}\n    exit-code: '1'\n    severity: 'CRITICAL,HIGH'\n","yaml",[2887],{"type":34,"tag":49,"props":2888,"children":2889},{"__ignoreMap":7},[2890,2899,2925,2942,2955,2972,2989],{"type":34,"tag":91,"props":2891,"children":2892},{"class":93,"line":94},[2893],{"type":34,"tag":91,"props":2894,"children":2896},{"style":2895},"--shiki-default:#6A737D",[2897],{"type":40,"value":2898},"# GitHub Actions step — fails PR if critical CVEs found\n",{"type":34,"tag":91,"props":2900,"children":2901},{"class":93,"line":103},[2902,2908,2914,2919],{"type":34,"tag":91,"props":2903,"children":2905},{"style":2904},"--shiki-default:#24292E",[2906],{"type":40,"value":2907},"- ",{"type":34,"tag":91,"props":2909,"children":2911},{"style":2910},"--shiki-default:#22863A",[2912],{"type":40,"value":2913},"name",{"type":34,"tag":91,"props":2915,"children":2916},{"style":2904},[2917],{"type":40,"value":2918},": ",{"type":34,"tag":91,"props":2920,"children":2922},{"style":2921},"--shiki-default:#032F62",[2923],{"type":40,"value":2924},"Scan image for vulnerabilities\n",{"type":34,"tag":91,"props":2926,"children":2927},{"class":93,"line":112},[2928,2933,2937],{"type":34,"tag":91,"props":2929,"children":2930},{"style":2910},[2931],{"type":40,"value":2932},"  uses",{"type":34,"tag":91,"props":2934,"children":2935},{"style":2904},[2936],{"type":40,"value":2918},{"type":34,"tag":91,"props":2938,"children":2939},{"style":2921},[2940],{"type":40,"value":2941},"aquasecurity/trivy-action@master\n",{"type":34,"tag":91,"props":2943,"children":2944},{"class":93,"line":121},[2945,2950],{"type":34,"tag":91,"props":2946,"children":2947},{"style":2910},[2948],{"type":40,"value":2949},"  with",{"type":34,"tag":91,"props":2951,"children":2952},{"style":2904},[2953],{"type":40,"value":2954},":\n",{"type":34,"tag":91,"props":2956,"children":2957},{"class":93,"line":131},[2958,2963,2967],{"type":34,"tag":91,"props":2959,"children":2960},{"style":2910},[2961],{"type":40,"value":2962},"    image-ref",{"type":34,"tag":91,"props":2964,"children":2965},{"style":2904},[2966],{"type":40,"value":2918},{"type":34,"tag":91,"props":2968,"children":2969},{"style":2921},[2970],{"type":40,"value":2971},"${{ env.IMAGE }}\n",{"type":34,"tag":91,"props":2973,"children":2974},{"class":93,"line":140},[2975,2980,2984],{"type":34,"tag":91,"props":2976,"children":2977},{"style":2910},[2978],{"type":40,"value":2979},"    exit-code",{"type":34,"tag":91,"props":2981,"children":2982},{"style":2904},[2983],{"type":40,"value":2918},{"type":34,"tag":91,"props":2985,"children":2986},{"style":2921},[2987],{"type":40,"value":2988},"'1'\n",{"type":34,"tag":91,"props":2990,"children":2991},{"class":93,"line":149},[2992,2997,3001],{"type":34,"tag":91,"props":2993,"children":2994},{"style":2910},[2995],{"type":40,"value":2996},"    severity",{"type":34,"tag":91,"props":2998,"children":2999},{"style":2904},[3000],{"type":40,"value":2918},{"type":34,"tag":91,"props":3002,"children":3003},{"style":2921},[3004],{"type":40,"value":3005},"'CRITICAL,HIGH'\n",{"type":34,"tag":35,"props":3007,"children":3009},{"id":3008},"composing-services-locally-with-docker-compose",[3010],{"type":40,"value":3011},"Composing Services Locally with Docker Compose",{"type":34,"tag":43,"props":3013,"children":3014},{},[3015],{"type":40,"value":3016},"Docker Compose is the right tool for local development and integration testing. Here's a production-mirroring setup with secrets management:",{"type":34,"tag":81,"props":3018,"children":3020},{"className":2883,"code":3019,"language":2885,"meta":7,"style":7},"services:\n  api:\n    build: ./api\n    ports: [\"8080:8080\"]\n    environment:\n      DB_HOST: db\n      DB_PASSWORD_FILE: /run/secrets/db_password\n    depends_on:\n      db:\n        condition: service_healthy\n    secrets: [db_password]\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8080/health\"]\n      interval: 30s\n      timeout: 5s\n      retries: 3\n      start_period: 10s\n\n  db:\n    image: postgres:16-alpine\n    volumes: [db_data:/var/lib/postgresql/data]\n    environment:\n      POSTGRES_PASSWORD_FILE: /run/secrets/db_password\n    secrets: [db_password]\n    healthcheck:\n      test: [\"CMD\", \"pg_isready\", \"-U\", \"postgres\"]\n      interval: 10s\n\nvolumes:\n  db_data:\n\nsecrets:\n  db_password:\n    file: ./secrets/db_password.txt\n",[3021],{"type":34,"tag":49,"props":3022,"children":3023},{"__ignoreMap":7},[3024,3036,3048,3065,3088,3100,3117,3134,3146,3158,3175,3196,3208,3257,3274,3291,3309,3326,3333,3345,3362,3383,3394,3410,3429,3440,3486,3501,3508,3520,3532,3539,3551,3563],{"type":34,"tag":91,"props":3025,"children":3026},{"class":93,"line":94},[3027,3032],{"type":34,"tag":91,"props":3028,"children":3029},{"style":2910},[3030],{"type":40,"value":3031},"services",{"type":34,"tag":91,"props":3033,"children":3034},{"style":2904},[3035],{"type":40,"value":2954},{"type":34,"tag":91,"props":3037,"children":3038},{"class":93,"line":103},[3039,3044],{"type":34,"tag":91,"props":3040,"children":3041},{"style":2910},[3042],{"type":40,"value":3043},"  api",{"type":34,"tag":91,"props":3045,"children":3046},{"style":2904},[3047],{"type":40,"value":2954},{"type":34,"tag":91,"props":3049,"children":3050},{"class":93,"line":112},[3051,3056,3060],{"type":34,"tag":91,"props":3052,"children":3053},{"style":2910},[3054],{"type":40,"value":3055},"    build",{"type":34,"tag":91,"props":3057,"children":3058},{"style":2904},[3059],{"type":40,"value":2918},{"type":34,"tag":91,"props":3061,"children":3062},{"style":2921},[3063],{"type":40,"value":3064},"./api\n",{"type":34,"tag":91,"props":3066,"children":3067},{"class":93,"line":121},[3068,3073,3078,3083],{"type":34,"tag":91,"props":3069,"children":3070},{"style":2910},[3071],{"type":40,"value":3072},"    ports",{"type":34,"tag":91,"props":3074,"children":3075},{"style":2904},[3076],{"type":40,"value":3077},": [",{"type":34,"tag":91,"props":3079,"children":3080},{"style":2921},[3081],{"type":40,"value":3082},"\"8080:8080\"",{"type":34,"tag":91,"props":3084,"children":3085},{"style":2904},[3086],{"type":40,"value":3087},"]\n",{"type":34,"tag":91,"props":3089,"children":3090},{"class":93,"line":131},[3091,3096],{"type":34,"tag":91,"props":3092,"children":3093},{"style":2910},[3094],{"type":40,"value":3095},"    environment",{"type":34,"tag":91,"props":3097,"children":3098},{"style":2904},[3099],{"type":40,"value":2954},{"type":34,"tag":91,"props":3101,"children":3102},{"class":93,"line":140},[3103,3108,3112],{"type":34,"tag":91,"props":3104,"children":3105},{"style":2910},[3106],{"type":40,"value":3107},"      DB_HOST",{"type":34,"tag":91,"props":3109,"children":3110},{"style":2904},[3111],{"type":40,"value":2918},{"type":34,"tag":91,"props":3113,"children":3114},{"style":2921},[3115],{"type":40,"value":3116},"db\n",{"type":34,"tag":91,"props":3118,"children":3119},{"class":93,"line":149},[3120,3125,3129],{"type":34,"tag":91,"props":3121,"children":3122},{"style":2910},[3123],{"type":40,"value":3124},"      DB_PASSWORD_FILE",{"type":34,"tag":91,"props":3126,"children":3127},{"style":2904},[3128],{"type":40,"value":2918},{"type":34,"tag":91,"props":3130,"children":3131},{"style":2921},[3132],{"type":40,"value":3133},"/run/secrets/db_password\n",{"type":34,"tag":91,"props":3135,"children":3136},{"class":93,"line":158},[3137,3142],{"type":34,"tag":91,"props":3138,"children":3139},{"style":2910},[3140],{"type":40,"value":3141},"    depends_on",{"type":34,"tag":91,"props":3143,"children":3144},{"style":2904},[3145],{"type":40,"value":2954},{"type":34,"tag":91,"props":3147,"children":3148},{"class":93,"line":167},[3149,3154],{"type":34,"tag":91,"props":3150,"children":3151},{"style":2910},[3152],{"type":40,"value":3153},"      db",{"type":34,"tag":91,"props":3155,"children":3156},{"style":2904},[3157],{"type":40,"value":2954},{"type":34,"tag":91,"props":3159,"children":3160},{"class":93,"line":176},[3161,3166,3170],{"type":34,"tag":91,"props":3162,"children":3163},{"style":2910},[3164],{"type":40,"value":3165},"        condition",{"type":34,"tag":91,"props":3167,"children":3168},{"style":2904},[3169],{"type":40,"value":2918},{"type":34,"tag":91,"props":3171,"children":3172},{"style":2921},[3173],{"type":40,"value":3174},"service_healthy\n",{"type":34,"tag":91,"props":3176,"children":3177},{"class":93,"line":184},[3178,3183,3187,3192],{"type":34,"tag":91,"props":3179,"children":3180},{"style":2910},[3181],{"type":40,"value":3182},"    secrets",{"type":34,"tag":91,"props":3184,"children":3185},{"style":2904},[3186],{"type":40,"value":3077},{"type":34,"tag":91,"props":3188,"children":3189},{"style":2921},[3190],{"type":40,"value":3191},"db_password",{"type":34,"tag":91,"props":3193,"children":3194},{"style":2904},[3195],{"type":40,"value":3087},{"type":34,"tag":91,"props":3197,"children":3198},{"class":93,"line":193},[3199,3204],{"type":34,"tag":91,"props":3200,"children":3201},{"style":2910},[3202],{"type":40,"value":3203},"    healthcheck",{"type":34,"tag":91,"props":3205,"children":3206},{"style":2904},[3207],{"type":40,"value":2954},{"type":34,"tag":91,"props":3209,"children":3210},{"class":93,"line":202},[3211,3216,3220,3225,3230,3235,3239,3244,3248,3253],{"type":34,"tag":91,"props":3212,"children":3213},{"style":2910},[3214],{"type":40,"value":3215},"      test",{"type":34,"tag":91,"props":3217,"children":3218},{"style":2904},[3219],{"type":40,"value":3077},{"type":34,"tag":91,"props":3221,"children":3222},{"style":2921},[3223],{"type":40,"value":3224},"\"CMD\"",{"type":34,"tag":91,"props":3226,"children":3227},{"style":2904},[3228],{"type":40,"value":3229},", ",{"type":34,"tag":91,"props":3231,"children":3232},{"style":2921},[3233],{"type":40,"value":3234},"\"curl\"",{"type":34,"tag":91,"props":3236,"children":3237},{"style":2904},[3238],{"type":40,"value":3229},{"type":34,"tag":91,"props":3240,"children":3241},{"style":2921},[3242],{"type":40,"value":3243},"\"-f\"",{"type":34,"tag":91,"props":3245,"children":3246},{"style":2904},[3247],{"type":40,"value":3229},{"type":34,"tag":91,"props":3249,"children":3250},{"style":2921},[3251],{"type":40,"value":3252},"\"http://localhost:8080/health\"",{"type":34,"tag":91,"props":3254,"children":3255},{"style":2904},[3256],{"type":40,"value":3087},{"type":34,"tag":91,"props":3258,"children":3259},{"class":93,"line":210},[3260,3265,3269],{"type":34,"tag":91,"props":3261,"children":3262},{"style":2910},[3263],{"type":40,"value":3264},"      interval",{"type":34,"tag":91,"props":3266,"children":3267},{"style":2904},[3268],{"type":40,"value":2918},{"type":34,"tag":91,"props":3270,"children":3271},{"style":2921},[3272],{"type":40,"value":3273},"30s\n",{"type":34,"tag":91,"props":3275,"children":3276},{"class":93,"line":218},[3277,3282,3286],{"type":34,"tag":91,"props":3278,"children":3279},{"style":2910},[3280],{"type":40,"value":3281},"      timeout",{"type":34,"tag":91,"props":3283,"children":3284},{"style":2904},[3285],{"type":40,"value":2918},{"type":34,"tag":91,"props":3287,"children":3288},{"style":2921},[3289],{"type":40,"value":3290},"5s\n",{"type":34,"tag":91,"props":3292,"children":3293},{"class":93,"line":227},[3294,3299,3303],{"type":34,"tag":91,"props":3295,"children":3296},{"style":2910},[3297],{"type":40,"value":3298},"      retries",{"type":34,"tag":91,"props":3300,"children":3301},{"style":2904},[3302],{"type":40,"value":2918},{"type":34,"tag":91,"props":3304,"children":3306},{"style":3305},"--shiki-default:#005CC5",[3307],{"type":40,"value":3308},"3\n",{"type":34,"tag":91,"props":3310,"children":3311},{"class":93,"line":236},[3312,3317,3321],{"type":34,"tag":91,"props":3313,"children":3314},{"style":2910},[3315],{"type":40,"value":3316},"      start_period",{"type":34,"tag":91,"props":3318,"children":3319},{"style":2904},[3320],{"type":40,"value":2918},{"type":34,"tag":91,"props":3322,"children":3323},{"style":2921},[3324],{"type":40,"value":3325},"10s\n",{"type":34,"tag":91,"props":3327,"children":3328},{"class":93,"line":245},[3329],{"type":34,"tag":91,"props":3330,"children":3331},{"emptyLinePlaceholder":125},[3332],{"type":40,"value":128},{"type":34,"tag":91,"props":3334,"children":3335},{"class":93,"line":254},[3336,3341],{"type":34,"tag":91,"props":3337,"children":3338},{"style":2910},[3339],{"type":40,"value":3340},"  db",{"type":34,"tag":91,"props":3342,"children":3343},{"style":2904},[3344],{"type":40,"value":2954},{"type":34,"tag":91,"props":3346,"children":3347},{"class":93,"line":262},[3348,3353,3357],{"type":34,"tag":91,"props":3349,"children":3350},{"style":2910},[3351],{"type":40,"value":3352},"    image",{"type":34,"tag":91,"props":3354,"children":3355},{"style":2904},[3356],{"type":40,"value":2918},{"type":34,"tag":91,"props":3358,"children":3359},{"style":2921},[3360],{"type":40,"value":3361},"postgres:16-alpine\n",{"type":34,"tag":91,"props":3363,"children":3364},{"class":93,"line":270},[3365,3370,3374,3379],{"type":34,"tag":91,"props":3366,"children":3367},{"style":2910},[3368],{"type":40,"value":3369},"    volumes",{"type":34,"tag":91,"props":3371,"children":3372},{"style":2904},[3373],{"type":40,"value":3077},{"type":34,"tag":91,"props":3375,"children":3376},{"style":2921},[3377],{"type":40,"value":3378},"db_data:/var/lib/postgresql/data",{"type":34,"tag":91,"props":3380,"children":3381},{"style":2904},[3382],{"type":40,"value":3087},{"type":34,"tag":91,"props":3384,"children":3385},{"class":93,"line":279},[3386,3390],{"type":34,"tag":91,"props":3387,"children":3388},{"style":2910},[3389],{"type":40,"value":3095},{"type":34,"tag":91,"props":3391,"children":3392},{"style":2904},[3393],{"type":40,"value":2954},{"type":34,"tag":91,"props":3395,"children":3396},{"class":93,"line":288},[3397,3402,3406],{"type":34,"tag":91,"props":3398,"children":3399},{"style":2910},[3400],{"type":40,"value":3401},"      POSTGRES_PASSWORD_FILE",{"type":34,"tag":91,"props":3403,"children":3404},{"style":2904},[3405],{"type":40,"value":2918},{"type":34,"tag":91,"props":3407,"children":3408},{"style":2921},[3409],{"type":40,"value":3133},{"type":34,"tag":91,"props":3411,"children":3412},{"class":93,"line":297},[3413,3417,3421,3425],{"type":34,"tag":91,"props":3414,"children":3415},{"style":2910},[3416],{"type":40,"value":3182},{"type":34,"tag":91,"props":3418,"children":3419},{"style":2904},[3420],{"type":40,"value":3077},{"type":34,"tag":91,"props":3422,"children":3423},{"style":2921},[3424],{"type":40,"value":3191},{"type":34,"tag":91,"props":3426,"children":3427},{"style":2904},[3428],{"type":40,"value":3087},{"type":34,"tag":91,"props":3430,"children":3431},{"class":93,"line":306},[3432,3436],{"type":34,"tag":91,"props":3433,"children":3434},{"style":2910},[3435],{"type":40,"value":3203},{"type":34,"tag":91,"props":3437,"children":3438},{"style":2904},[3439],{"type":40,"value":2954},{"type":34,"tag":91,"props":3441,"children":3442},{"class":93,"line":315},[3443,3447,3451,3455,3459,3464,3468,3473,3477,3482],{"type":34,"tag":91,"props":3444,"children":3445},{"style":2910},[3446],{"type":40,"value":3215},{"type":34,"tag":91,"props":3448,"children":3449},{"style":2904},[3450],{"type":40,"value":3077},{"type":34,"tag":91,"props":3452,"children":3453},{"style":2921},[3454],{"type":40,"value":3224},{"type":34,"tag":91,"props":3456,"children":3457},{"style":2904},[3458],{"type":40,"value":3229},{"type":34,"tag":91,"props":3460,"children":3461},{"style":2921},[3462],{"type":40,"value":3463},"\"pg_isready\"",{"type":34,"tag":91,"props":3465,"children":3466},{"style":2904},[3467],{"type":40,"value":3229},{"type":34,"tag":91,"props":3469,"children":3470},{"style":2921},[3471],{"type":40,"value":3472},"\"-U\"",{"type":34,"tag":91,"props":3474,"children":3475},{"style":2904},[3476],{"type":40,"value":3229},{"type":34,"tag":91,"props":3478,"children":3479},{"style":2921},[3480],{"type":40,"value":3481},"\"postgres\"",{"type":34,"tag":91,"props":3483,"children":3484},{"style":2904},[3485],{"type":40,"value":3087},{"type":34,"tag":91,"props":3487,"children":3488},{"class":93,"line":324},[3489,3493,3497],{"type":34,"tag":91,"props":3490,"children":3491},{"style":2910},[3492],{"type":40,"value":3264},{"type":34,"tag":91,"props":3494,"children":3495},{"style":2904},[3496],{"type":40,"value":2918},{"type":34,"tag":91,"props":3498,"children":3499},{"style":2921},[3500],{"type":40,"value":3325},{"type":34,"tag":91,"props":3502,"children":3503},{"class":93,"line":333},[3504],{"type":34,"tag":91,"props":3505,"children":3506},{"emptyLinePlaceholder":125},[3507],{"type":40,"value":128},{"type":34,"tag":91,"props":3509,"children":3510},{"class":93,"line":342},[3511,3516],{"type":34,"tag":91,"props":3512,"children":3513},{"style":2910},[3514],{"type":40,"value":3515},"volumes",{"type":34,"tag":91,"props":3517,"children":3518},{"style":2904},[3519],{"type":40,"value":2954},{"type":34,"tag":91,"props":3521,"children":3522},{"class":93,"line":612},[3523,3528],{"type":34,"tag":91,"props":3524,"children":3525},{"style":2910},[3526],{"type":40,"value":3527},"  db_data",{"type":34,"tag":91,"props":3529,"children":3530},{"style":2904},[3531],{"type":40,"value":2954},{"type":34,"tag":91,"props":3533,"children":3534},{"class":93,"line":621},[3535],{"type":34,"tag":91,"props":3536,"children":3537},{"emptyLinePlaceholder":125},[3538],{"type":40,"value":128},{"type":34,"tag":91,"props":3540,"children":3541},{"class":93,"line":630},[3542,3547],{"type":34,"tag":91,"props":3543,"children":3544},{"style":2910},[3545],{"type":40,"value":3546},"secrets",{"type":34,"tag":91,"props":3548,"children":3549},{"style":2904},[3550],{"type":40,"value":2954},{"type":34,"tag":91,"props":3552,"children":3553},{"class":93,"line":639},[3554,3559],{"type":34,"tag":91,"props":3555,"children":3556},{"style":2910},[3557],{"type":40,"value":3558},"  db_password",{"type":34,"tag":91,"props":3560,"children":3561},{"style":2904},[3562],{"type":40,"value":2954},{"type":34,"tag":91,"props":3564,"children":3565},{"class":93,"line":648},[3566,3571,3575],{"type":34,"tag":91,"props":3567,"children":3568},{"style":2910},[3569],{"type":40,"value":3570},"    file",{"type":34,"tag":91,"props":3572,"children":3573},{"style":2904},[3574],{"type":40,"value":2918},{"type":34,"tag":91,"props":3576,"children":3577},{"style":2921},[3578],{"type":40,"value":3579},"./secrets/db_password.txt\n",{"type":34,"tag":43,"props":3581,"children":3582},{},[3583,3585,3591,3593,3599],{"type":40,"value":3584},"Two things worth highlighting here: ",{"type":34,"tag":49,"props":3586,"children":3588},{"className":3587},[],[3589],{"type":40,"value":3590},"depends_on",{"type":40,"value":3592}," with ",{"type":34,"tag":49,"props":3594,"children":3596},{"className":3595},[],[3597],{"type":40,"value":3598},"condition: service_healthy",{"type":40,"value":3600}," ensures the API only starts once the database is truly ready (not just the container process), and secrets are mounted as files rather than plain environment variables—reducing the risk of accidental exposure in logs.",{"type":34,"tag":35,"props":3602,"children":3604},{"id":3603},"kubernetes-orchestration-that-scales",[3605],{"type":40,"value":3606},"Kubernetes: Orchestration That Scales",{"type":34,"tag":43,"props":3608,"children":3609},{},[3610],{"type":40,"value":3611},"Kubernetes (K8s) takes over where Docker Compose leaves off. When you need automatic self-healing, zero-downtime deploys, and the ability to run hundreds of container replicas across a cluster, Kubernetes is the answer.",{"type":34,"tag":2626,"props":3613,"children":3615},{"id":3614},"core-kubernetes-primitives",[3616],{"type":40,"value":3617},"Core Kubernetes Primitives",{"type":34,"tag":1968,"props":3619,"children":3620},{},[3621,3637],{"type":34,"tag":1972,"props":3622,"children":3623},{},[3624],{"type":34,"tag":1976,"props":3625,"children":3626},{},[3627,3632],{"type":34,"tag":1980,"props":3628,"children":3629},{},[3630],{"type":40,"value":3631},"Object",{"type":34,"tag":1980,"props":3633,"children":3634},{},[3635],{"type":40,"value":3636},"Purpose",{"type":34,"tag":1996,"props":3638,"children":3639},{},[3640,3656,3672,3687,3703],{"type":34,"tag":1976,"props":3641,"children":3642},{},[3643,3651],{"type":34,"tag":2003,"props":3644,"children":3645},{},[3646],{"type":34,"tag":1770,"props":3647,"children":3648},{},[3649],{"type":40,"value":3650},"Pod",{"type":34,"tag":2003,"props":3652,"children":3653},{},[3654],{"type":40,"value":3655},"Smallest deployable unit; one or more containers sharing networking and storage",{"type":34,"tag":1976,"props":3657,"children":3658},{},[3659,3667],{"type":34,"tag":2003,"props":3660,"children":3661},{},[3662],{"type":34,"tag":1770,"props":3663,"children":3664},{},[3665],{"type":40,"value":3666},"Deployment",{"type":34,"tag":2003,"props":3668,"children":3669},{},[3670],{"type":40,"value":3671},"Declares desired state; manages rolling updates and rollbacks",{"type":34,"tag":1976,"props":3673,"children":3674},{},[3675,3682],{"type":34,"tag":2003,"props":3676,"children":3677},{},[3678],{"type":34,"tag":1770,"props":3679,"children":3680},{},[3681],{"type":40,"value":1984},{"type":34,"tag":2003,"props":3683,"children":3684},{},[3685],{"type":40,"value":3686},"Stable network endpoint in front of a set of pods",{"type":34,"tag":1976,"props":3688,"children":3689},{},[3690,3698],{"type":34,"tag":2003,"props":3691,"children":3692},{},[3693],{"type":34,"tag":1770,"props":3694,"children":3695},{},[3696],{"type":40,"value":3697},"ConfigMap / Secret",{"type":34,"tag":2003,"props":3699,"children":3700},{},[3701],{"type":40,"value":3702},"Externalise configuration and credentials from images",{"type":34,"tag":1976,"props":3704,"children":3705},{},[3706,3714],{"type":34,"tag":2003,"props":3707,"children":3708},{},[3709],{"type":34,"tag":1770,"props":3710,"children":3711},{},[3712],{"type":40,"value":3713},"HorizontalPodAutoscaler",{"type":34,"tag":2003,"props":3715,"children":3716},{},[3717],{"type":40,"value":3718},"Automatically scales replica count based on CPU, memory, or custom metrics",{"type":34,"tag":2626,"props":3720,"children":3722},{"id":3721},"a-production-deployment-manifest",[3723],{"type":40,"value":3724},"A Production Deployment Manifest",{"type":34,"tag":81,"props":3726,"children":3728},{"className":2883,"code":3727,"language":2885,"meta":7,"style":7},"apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: order-service\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: order-service\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0       # Never take a pod down before a new one is ready\n      maxSurge: 1\n  template:\n    metadata:\n      labels:\n        app: order-service\n    spec:\n      containers:\n      - name: order-service\n        image: registry.example.com/order-service:v2.4.1\n        ports: [{containerPort: 8080}]\n        resources:\n          requests:\n            cpu: \"250m\"\n            memory: \"256Mi\"\n          limits:\n            cpu: \"500m\"\n            memory: \"512Mi\"\n        livenessProbe:\n          httpGet:\n            path: /health/live\n            port: 8080\n          initialDelaySeconds: 10\n          periodSeconds: 15\n        readinessProbe:\n          httpGet:\n            path: /health/ready\n            port: 8080\n          initialDelaySeconds: 5\n          periodSeconds: 10\n        securityContext:\n          runAsNonRoot: true\n          readOnlyRootFilesystem: true\n",[3729],{"type":34,"tag":49,"props":3730,"children":3731},{"__ignoreMap":7},[3732,3749,3766,3778,3795,3807,3823,3835,3847,3863,3875,3892,3904,3926,3943,3955,3967,3979,3995,4007,4019,4039,4056,4088,4100,4112,4129,4146,4158,4174,4190,4202,4214,4231,4248,4265,4282,4294,4305,4321,4336,4352,4367,4379,4396],{"type":34,"tag":91,"props":3733,"children":3734},{"class":93,"line":94},[3735,3740,3744],{"type":34,"tag":91,"props":3736,"children":3737},{"style":2910},[3738],{"type":40,"value":3739},"apiVersion",{"type":34,"tag":91,"props":3741,"children":3742},{"style":2904},[3743],{"type":40,"value":2918},{"type":34,"tag":91,"props":3745,"children":3746},{"style":2921},[3747],{"type":40,"value":3748},"apps/v1\n",{"type":34,"tag":91,"props":3750,"children":3751},{"class":93,"line":103},[3752,3757,3761],{"type":34,"tag":91,"props":3753,"children":3754},{"style":2910},[3755],{"type":40,"value":3756},"kind",{"type":34,"tag":91,"props":3758,"children":3759},{"style":2904},[3760],{"type":40,"value":2918},{"type":34,"tag":91,"props":3762,"children":3763},{"style":2921},[3764],{"type":40,"value":3765},"Deployment\n",{"type":34,"tag":91,"props":3767,"children":3768},{"class":93,"line":112},[3769,3774],{"type":34,"tag":91,"props":3770,"children":3771},{"style":2910},[3772],{"type":40,"value":3773},"metadata",{"type":34,"tag":91,"props":3775,"children":3776},{"style":2904},[3777],{"type":40,"value":2954},{"type":34,"tag":91,"props":3779,"children":3780},{"class":93,"line":121},[3781,3786,3790],{"type":34,"tag":91,"props":3782,"children":3783},{"style":2910},[3784],{"type":40,"value":3785},"  name",{"type":34,"tag":91,"props":3787,"children":3788},{"style":2904},[3789],{"type":40,"value":2918},{"type":34,"tag":91,"props":3791,"children":3792},{"style":2921},[3793],{"type":40,"value":3794},"order-service\n",{"type":34,"tag":91,"props":3796,"children":3797},{"class":93,"line":131},[3798,3803],{"type":34,"tag":91,"props":3799,"children":3800},{"style":2910},[3801],{"type":40,"value":3802},"spec",{"type":34,"tag":91,"props":3804,"children":3805},{"style":2904},[3806],{"type":40,"value":2954},{"type":34,"tag":91,"props":3808,"children":3809},{"class":93,"line":140},[3810,3815,3819],{"type":34,"tag":91,"props":3811,"children":3812},{"style":2910},[3813],{"type":40,"value":3814},"  replicas",{"type":34,"tag":91,"props":3816,"children":3817},{"style":2904},[3818],{"type":40,"value":2918},{"type":34,"tag":91,"props":3820,"children":3821},{"style":3305},[3822],{"type":40,"value":3308},{"type":34,"tag":91,"props":3824,"children":3825},{"class":93,"line":149},[3826,3831],{"type":34,"tag":91,"props":3827,"children":3828},{"style":2910},[3829],{"type":40,"value":3830},"  selector",{"type":34,"tag":91,"props":3832,"children":3833},{"style":2904},[3834],{"type":40,"value":2954},{"type":34,"tag":91,"props":3836,"children":3837},{"class":93,"line":158},[3838,3843],{"type":34,"tag":91,"props":3839,"children":3840},{"style":2910},[3841],{"type":40,"value":3842},"    matchLabels",{"type":34,"tag":91,"props":3844,"children":3845},{"style":2904},[3846],{"type":40,"value":2954},{"type":34,"tag":91,"props":3848,"children":3849},{"class":93,"line":167},[3850,3855,3859],{"type":34,"tag":91,"props":3851,"children":3852},{"style":2910},[3853],{"type":40,"value":3854},"      app",{"type":34,"tag":91,"props":3856,"children":3857},{"style":2904},[3858],{"type":40,"value":2918},{"type":34,"tag":91,"props":3860,"children":3861},{"style":2921},[3862],{"type":40,"value":3794},{"type":34,"tag":91,"props":3864,"children":3865},{"class":93,"line":176},[3866,3871],{"type":34,"tag":91,"props":3867,"children":3868},{"style":2910},[3869],{"type":40,"value":3870},"  strategy",{"type":34,"tag":91,"props":3872,"children":3873},{"style":2904},[3874],{"type":40,"value":2954},{"type":34,"tag":91,"props":3876,"children":3877},{"class":93,"line":184},[3878,3883,3887],{"type":34,"tag":91,"props":3879,"children":3880},{"style":2910},[3881],{"type":40,"value":3882},"    type",{"type":34,"tag":91,"props":3884,"children":3885},{"style":2904},[3886],{"type":40,"value":2918},{"type":34,"tag":91,"props":3888,"children":3889},{"style":2921},[3890],{"type":40,"value":3891},"RollingUpdate\n",{"type":34,"tag":91,"props":3893,"children":3894},{"class":93,"line":193},[3895,3900],{"type":34,"tag":91,"props":3896,"children":3897},{"style":2910},[3898],{"type":40,"value":3899},"    rollingUpdate",{"type":34,"tag":91,"props":3901,"children":3902},{"style":2904},[3903],{"type":40,"value":2954},{"type":34,"tag":91,"props":3905,"children":3906},{"class":93,"line":202},[3907,3912,3916,3921],{"type":34,"tag":91,"props":3908,"children":3909},{"style":2910},[3910],{"type":40,"value":3911},"      maxUnavailable",{"type":34,"tag":91,"props":3913,"children":3914},{"style":2904},[3915],{"type":40,"value":2918},{"type":34,"tag":91,"props":3917,"children":3918},{"style":3305},[3919],{"type":40,"value":3920},"0",{"type":34,"tag":91,"props":3922,"children":3923},{"style":2895},[3924],{"type":40,"value":3925},"       # Never take a pod down before a new one is ready\n",{"type":34,"tag":91,"props":3927,"children":3928},{"class":93,"line":210},[3929,3934,3938],{"type":34,"tag":91,"props":3930,"children":3931},{"style":2910},[3932],{"type":40,"value":3933},"      maxSurge",{"type":34,"tag":91,"props":3935,"children":3936},{"style":2904},[3937],{"type":40,"value":2918},{"type":34,"tag":91,"props":3939,"children":3940},{"style":3305},[3941],{"type":40,"value":3942},"1\n",{"type":34,"tag":91,"props":3944,"children":3945},{"class":93,"line":218},[3946,3951],{"type":34,"tag":91,"props":3947,"children":3948},{"style":2910},[3949],{"type":40,"value":3950},"  template",{"type":34,"tag":91,"props":3952,"children":3953},{"style":2904},[3954],{"type":40,"value":2954},{"type":34,"tag":91,"props":3956,"children":3957},{"class":93,"line":227},[3958,3963],{"type":34,"tag":91,"props":3959,"children":3960},{"style":2910},[3961],{"type":40,"value":3962},"    metadata",{"type":34,"tag":91,"props":3964,"children":3965},{"style":2904},[3966],{"type":40,"value":2954},{"type":34,"tag":91,"props":3968,"children":3969},{"class":93,"line":236},[3970,3975],{"type":34,"tag":91,"props":3971,"children":3972},{"style":2910},[3973],{"type":40,"value":3974},"      labels",{"type":34,"tag":91,"props":3976,"children":3977},{"style":2904},[3978],{"type":40,"value":2954},{"type":34,"tag":91,"props":3980,"children":3981},{"class":93,"line":245},[3982,3987,3991],{"type":34,"tag":91,"props":3983,"children":3984},{"style":2910},[3985],{"type":40,"value":3986},"        app",{"type":34,"tag":91,"props":3988,"children":3989},{"style":2904},[3990],{"type":40,"value":2918},{"type":34,"tag":91,"props":3992,"children":3993},{"style":2921},[3994],{"type":40,"value":3794},{"type":34,"tag":91,"props":3996,"children":3997},{"class":93,"line":254},[3998,4003],{"type":34,"tag":91,"props":3999,"children":4000},{"style":2910},[4001],{"type":40,"value":4002},"    spec",{"type":34,"tag":91,"props":4004,"children":4005},{"style":2904},[4006],{"type":40,"value":2954},{"type":34,"tag":91,"props":4008,"children":4009},{"class":93,"line":262},[4010,4015],{"type":34,"tag":91,"props":4011,"children":4012},{"style":2910},[4013],{"type":40,"value":4014},"      containers",{"type":34,"tag":91,"props":4016,"children":4017},{"style":2904},[4018],{"type":40,"value":2954},{"type":34,"tag":91,"props":4020,"children":4021},{"class":93,"line":270},[4022,4027,4031,4035],{"type":34,"tag":91,"props":4023,"children":4024},{"style":2904},[4025],{"type":40,"value":4026},"      - ",{"type":34,"tag":91,"props":4028,"children":4029},{"style":2910},[4030],{"type":40,"value":2913},{"type":34,"tag":91,"props":4032,"children":4033},{"style":2904},[4034],{"type":40,"value":2918},{"type":34,"tag":91,"props":4036,"children":4037},{"style":2921},[4038],{"type":40,"value":3794},{"type":34,"tag":91,"props":4040,"children":4041},{"class":93,"line":279},[4042,4047,4051],{"type":34,"tag":91,"props":4043,"children":4044},{"style":2910},[4045],{"type":40,"value":4046},"        image",{"type":34,"tag":91,"props":4048,"children":4049},{"style":2904},[4050],{"type":40,"value":2918},{"type":34,"tag":91,"props":4052,"children":4053},{"style":2921},[4054],{"type":40,"value":4055},"registry.example.com/order-service:v2.4.1\n",{"type":34,"tag":91,"props":4057,"children":4058},{"class":93,"line":288},[4059,4064,4069,4074,4078,4083],{"type":34,"tag":91,"props":4060,"children":4061},{"style":2910},[4062],{"type":40,"value":4063},"        ports",{"type":34,"tag":91,"props":4065,"children":4066},{"style":2904},[4067],{"type":40,"value":4068},": [{",{"type":34,"tag":91,"props":4070,"children":4071},{"style":2910},[4072],{"type":40,"value":4073},"containerPort",{"type":34,"tag":91,"props":4075,"children":4076},{"style":2904},[4077],{"type":40,"value":2918},{"type":34,"tag":91,"props":4079,"children":4080},{"style":3305},[4081],{"type":40,"value":4082},"8080",{"type":34,"tag":91,"props":4084,"children":4085},{"style":2904},[4086],{"type":40,"value":4087},"}]\n",{"type":34,"tag":91,"props":4089,"children":4090},{"class":93,"line":297},[4091,4096],{"type":34,"tag":91,"props":4092,"children":4093},{"style":2910},[4094],{"type":40,"value":4095},"        resources",{"type":34,"tag":91,"props":4097,"children":4098},{"style":2904},[4099],{"type":40,"value":2954},{"type":34,"tag":91,"props":4101,"children":4102},{"class":93,"line":306},[4103,4108],{"type":34,"tag":91,"props":4104,"children":4105},{"style":2910},[4106],{"type":40,"value":4107},"          requests",{"type":34,"tag":91,"props":4109,"children":4110},{"style":2904},[4111],{"type":40,"value":2954},{"type":34,"tag":91,"props":4113,"children":4114},{"class":93,"line":315},[4115,4120,4124],{"type":34,"tag":91,"props":4116,"children":4117},{"style":2910},[4118],{"type":40,"value":4119},"            cpu",{"type":34,"tag":91,"props":4121,"children":4122},{"style":2904},[4123],{"type":40,"value":2918},{"type":34,"tag":91,"props":4125,"children":4126},{"style":2921},[4127],{"type":40,"value":4128},"\"250m\"\n",{"type":34,"tag":91,"props":4130,"children":4131},{"class":93,"line":324},[4132,4137,4141],{"type":34,"tag":91,"props":4133,"children":4134},{"style":2910},[4135],{"type":40,"value":4136},"            memory",{"type":34,"tag":91,"props":4138,"children":4139},{"style":2904},[4140],{"type":40,"value":2918},{"type":34,"tag":91,"props":4142,"children":4143},{"style":2921},[4144],{"type":40,"value":4145},"\"256Mi\"\n",{"type":34,"tag":91,"props":4147,"children":4148},{"class":93,"line":333},[4149,4154],{"type":34,"tag":91,"props":4150,"children":4151},{"style":2910},[4152],{"type":40,"value":4153},"          limits",{"type":34,"tag":91,"props":4155,"children":4156},{"style":2904},[4157],{"type":40,"value":2954},{"type":34,"tag":91,"props":4159,"children":4160},{"class":93,"line":342},[4161,4165,4169],{"type":34,"tag":91,"props":4162,"children":4163},{"style":2910},[4164],{"type":40,"value":4119},{"type":34,"tag":91,"props":4166,"children":4167},{"style":2904},[4168],{"type":40,"value":2918},{"type":34,"tag":91,"props":4170,"children":4171},{"style":2921},[4172],{"type":40,"value":4173},"\"500m\"\n",{"type":34,"tag":91,"props":4175,"children":4176},{"class":93,"line":612},[4177,4181,4185],{"type":34,"tag":91,"props":4178,"children":4179},{"style":2910},[4180],{"type":40,"value":4136},{"type":34,"tag":91,"props":4182,"children":4183},{"style":2904},[4184],{"type":40,"value":2918},{"type":34,"tag":91,"props":4186,"children":4187},{"style":2921},[4188],{"type":40,"value":4189},"\"512Mi\"\n",{"type":34,"tag":91,"props":4191,"children":4192},{"class":93,"line":621},[4193,4198],{"type":34,"tag":91,"props":4194,"children":4195},{"style":2910},[4196],{"type":40,"value":4197},"        livenessProbe",{"type":34,"tag":91,"props":4199,"children":4200},{"style":2904},[4201],{"type":40,"value":2954},{"type":34,"tag":91,"props":4203,"children":4204},{"class":93,"line":630},[4205,4210],{"type":34,"tag":91,"props":4206,"children":4207},{"style":2910},[4208],{"type":40,"value":4209},"          httpGet",{"type":34,"tag":91,"props":4211,"children":4212},{"style":2904},[4213],{"type":40,"value":2954},{"type":34,"tag":91,"props":4215,"children":4216},{"class":93,"line":639},[4217,4222,4226],{"type":34,"tag":91,"props":4218,"children":4219},{"style":2910},[4220],{"type":40,"value":4221},"            path",{"type":34,"tag":91,"props":4223,"children":4224},{"style":2904},[4225],{"type":40,"value":2918},{"type":34,"tag":91,"props":4227,"children":4228},{"style":2921},[4229],{"type":40,"value":4230},"/health/live\n",{"type":34,"tag":91,"props":4232,"children":4233},{"class":93,"line":648},[4234,4239,4243],{"type":34,"tag":91,"props":4235,"children":4236},{"style":2910},[4237],{"type":40,"value":4238},"            port",{"type":34,"tag":91,"props":4240,"children":4241},{"style":2904},[4242],{"type":40,"value":2918},{"type":34,"tag":91,"props":4244,"children":4245},{"style":3305},[4246],{"type":40,"value":4247},"8080\n",{"type":34,"tag":91,"props":4249,"children":4250},{"class":93,"line":656},[4251,4256,4260],{"type":34,"tag":91,"props":4252,"children":4253},{"style":2910},[4254],{"type":40,"value":4255},"          initialDelaySeconds",{"type":34,"tag":91,"props":4257,"children":4258},{"style":2904},[4259],{"type":40,"value":2918},{"type":34,"tag":91,"props":4261,"children":4262},{"style":3305},[4263],{"type":40,"value":4264},"10\n",{"type":34,"tag":91,"props":4266,"children":4267},{"class":93,"line":664},[4268,4273,4277],{"type":34,"tag":91,"props":4269,"children":4270},{"style":2910},[4271],{"type":40,"value":4272},"          periodSeconds",{"type":34,"tag":91,"props":4274,"children":4275},{"style":2904},[4276],{"type":40,"value":2918},{"type":34,"tag":91,"props":4278,"children":4279},{"style":3305},[4280],{"type":40,"value":4281},"15\n",{"type":34,"tag":91,"props":4283,"children":4284},{"class":93,"line":673},[4285,4290],{"type":34,"tag":91,"props":4286,"children":4287},{"style":2910},[4288],{"type":40,"value":4289},"        readinessProbe",{"type":34,"tag":91,"props":4291,"children":4292},{"style":2904},[4293],{"type":40,"value":2954},{"type":34,"tag":91,"props":4295,"children":4296},{"class":93,"line":681},[4297,4301],{"type":34,"tag":91,"props":4298,"children":4299},{"style":2910},[4300],{"type":40,"value":4209},{"type":34,"tag":91,"props":4302,"children":4303},{"style":2904},[4304],{"type":40,"value":2954},{"type":34,"tag":91,"props":4306,"children":4307},{"class":93,"line":689},[4308,4312,4316],{"type":34,"tag":91,"props":4309,"children":4310},{"style":2910},[4311],{"type":40,"value":4221},{"type":34,"tag":91,"props":4313,"children":4314},{"style":2904},[4315],{"type":40,"value":2918},{"type":34,"tag":91,"props":4317,"children":4318},{"style":2921},[4319],{"type":40,"value":4320},"/health/ready\n",{"type":34,"tag":91,"props":4322,"children":4323},{"class":93,"line":698},[4324,4328,4332],{"type":34,"tag":91,"props":4325,"children":4326},{"style":2910},[4327],{"type":40,"value":4238},{"type":34,"tag":91,"props":4329,"children":4330},{"style":2904},[4331],{"type":40,"value":2918},{"type":34,"tag":91,"props":4333,"children":4334},{"style":3305},[4335],{"type":40,"value":4247},{"type":34,"tag":91,"props":4337,"children":4338},{"class":93,"line":707},[4339,4343,4347],{"type":34,"tag":91,"props":4340,"children":4341},{"style":2910},[4342],{"type":40,"value":4255},{"type":34,"tag":91,"props":4344,"children":4345},{"style":2904},[4346],{"type":40,"value":2918},{"type":34,"tag":91,"props":4348,"children":4349},{"style":3305},[4350],{"type":40,"value":4351},"5\n",{"type":34,"tag":91,"props":4353,"children":4354},{"class":93,"line":716},[4355,4359,4363],{"type":34,"tag":91,"props":4356,"children":4357},{"style":2910},[4358],{"type":40,"value":4272},{"type":34,"tag":91,"props":4360,"children":4361},{"style":2904},[4362],{"type":40,"value":2918},{"type":34,"tag":91,"props":4364,"children":4365},{"style":3305},[4366],{"type":40,"value":4264},{"type":34,"tag":91,"props":4368,"children":4369},{"class":93,"line":725},[4370,4375],{"type":34,"tag":91,"props":4371,"children":4372},{"style":2910},[4373],{"type":40,"value":4374},"        securityContext",{"type":34,"tag":91,"props":4376,"children":4377},{"style":2904},[4378],{"type":40,"value":2954},{"type":34,"tag":91,"props":4380,"children":4381},{"class":93,"line":734},[4382,4387,4391],{"type":34,"tag":91,"props":4383,"children":4384},{"style":2910},[4385],{"type":40,"value":4386},"          runAsNonRoot",{"type":34,"tag":91,"props":4388,"children":4389},{"style":2904},[4390],{"type":40,"value":2918},{"type":34,"tag":91,"props":4392,"children":4393},{"style":3305},[4394],{"type":40,"value":4395},"true\n",{"type":34,"tag":91,"props":4397,"children":4398},{"class":93,"line":742},[4399,4404,4408],{"type":34,"tag":91,"props":4400,"children":4401},{"style":2910},[4402],{"type":40,"value":4403},"          readOnlyRootFilesystem",{"type":34,"tag":91,"props":4405,"children":4406},{"style":2904},[4407],{"type":40,"value":2918},{"type":34,"tag":91,"props":4409,"children":4410},{"style":3305},[4411],{"type":40,"value":4395},{"type":34,"tag":43,"props":4413,"children":4414},{},[4415,4417,4423,4425,4431],{"type":40,"value":4416},"Setting ",{"type":34,"tag":49,"props":4418,"children":4420},{"className":4419},[],[4421],{"type":40,"value":4422},"maxUnavailable: 0",{"type":40,"value":4424}," and ",{"type":34,"tag":49,"props":4426,"children":4428},{"className":4427},[],[4429],{"type":40,"value":4430},"maxSurge: 1",{"type":40,"value":4432}," means Kubernetes always keeps the full replica count healthy during a rollout — zero-downtime deploys become the default.",{"type":34,"tag":35,"props":4434,"children":4436},{"id":4435},"case-study-containerising-a-legacy-net-platform",[4437],{"type":40,"value":4438},"Case Study: Containerising a Legacy .NET Platform",{"type":34,"tag":43,"props":4440,"children":4441},{},[4442],{"type":40,"value":4443},"A financial services client came to us with a Windows-server monolith that took three hours to deploy and consistently caused configuration drift between environments. Our containerisation project over eight weeks delivered:",{"type":34,"tag":1968,"props":4445,"children":4446},{},[4447,4468],{"type":34,"tag":1972,"props":4448,"children":4449},{},[4450],{"type":34,"tag":1976,"props":4451,"children":4452},{},[4453,4458,4463],{"type":34,"tag":1980,"props":4454,"children":4455},{},[4456],{"type":40,"value":4457},"Metric",{"type":34,"tag":1980,"props":4459,"children":4460},{},[4461],{"type":40,"value":4462},"Before",{"type":34,"tag":1980,"props":4464,"children":4465},{},[4466],{"type":40,"value":4467},"After",{"type":34,"tag":1996,"props":4469,"children":4470},{},[4471,4489,4507,4525],{"type":34,"tag":1976,"props":4472,"children":4473},{},[4474,4479,4484],{"type":34,"tag":2003,"props":4475,"children":4476},{},[4477],{"type":40,"value":4478},"Deployment time",{"type":34,"tag":2003,"props":4480,"children":4481},{},[4482],{"type":40,"value":4483},"~3 hours",{"type":34,"tag":2003,"props":4485,"children":4486},{},[4487],{"type":40,"value":4488},"~8 minutes",{"type":34,"tag":1976,"props":4490,"children":4491},{},[4492,4497,4502],{"type":34,"tag":2003,"props":4493,"children":4494},{},[4495],{"type":40,"value":4496},"Environment parity",{"type":34,"tag":2003,"props":4498,"children":4499},{},[4500],{"type":40,"value":4501},"❌ frequent drift",{"type":34,"tag":2003,"props":4503,"children":4504},{},[4505],{"type":40,"value":4506},"✅ identical images",{"type":34,"tag":1976,"props":4508,"children":4509},{},[4510,4515,4520],{"type":34,"tag":2003,"props":4511,"children":4512},{},[4513],{"type":40,"value":4514},"Infrastructure cost",{"type":34,"tag":2003,"props":4516,"children":4517},{},[4518],{"type":40,"value":4519},"baseline",{"type":34,"tag":2003,"props":4521,"children":4522},{},[4523],{"type":40,"value":4524},"−40%",{"type":34,"tag":1976,"props":4526,"children":4527},{},[4528,4533,4538],{"type":34,"tag":2003,"props":4529,"children":4530},{},[4531],{"type":40,"value":4532},"Release cadence",{"type":34,"tag":2003,"props":4534,"children":4535},{},[4536],{"type":40,"value":4537},"monthly",{"type":34,"tag":2003,"props":4539,"children":4540},{},[4541],{"type":40,"value":4542},"weekly",{"type":34,"tag":43,"props":4544,"children":4545},{},[4546],{"type":40,"value":4547},"The key steps: extracting configuration into environment variables, adding structured health-check endpoints the probes could target, building images in CI using multi-stage Dockerfiles, and deploying to AKS with Helm charts versioned alongside the application code.",{"type":34,"tag":35,"props":4549,"children":4551},{"id":4550},"what-to-containerise-first",[4552],{"type":40,"value":4553},"What to Containerise First",{"type":34,"tag":43,"props":4555,"children":4556},{},[4557],{"type":40,"value":4558},"Not everything benefits equally from containerisation. Start here:",{"type":34,"tag":2129,"props":4560,"children":4561},{},[4562,4572,4582],{"type":34,"tag":1766,"props":4563,"children":4564},{},[4565,4570],{"type":34,"tag":1770,"props":4566,"children":4567},{},[4568],{"type":40,"value":4569},"Stateless HTTP services",{"type":40,"value":4571}," — the easiest wins with the highest immediate benefit",{"type":34,"tag":1766,"props":4573,"children":4574},{},[4575,4580],{"type":34,"tag":1770,"props":4576,"children":4577},{},[4578],{"type":40,"value":4579},"Background workers and scheduled jobs",{"type":40,"value":4581}," — clean separation of concerns from your main API",{"type":34,"tag":1766,"props":4583,"children":4584},{},[4585,4590],{"type":34,"tag":1770,"props":4586,"children":4587},{},[4588],{"type":40,"value":4589},"Third-party dependencies in dev",{"type":40,"value":4591}," (databases, queues, email servers) — Compose makes local parity trivial",{"type":34,"tag":43,"props":4593,"children":4594},{},[4595],{"type":40,"value":4596},"Tackle stateful services (primary databases, file stores) last, and only when you have a solid understanding of volume management and backup strategies in your target cluster.",{"type":34,"tag":43,"props":4598,"children":4599},{},[4600],{"type":40,"value":4601},"Containerisation isn't a destination—it's the foundation for everything from zero-downtime deployments to auto-scaling to disaster recovery. Build the discipline into your workflow from day one.",{"type":34,"tag":1823,"props":4603,"children":4604},{},[4605],{"type":40,"value":1827},{"title":7,"searchDepth":112,"depth":112,"links":4607},[4608,4609,4610,4614,4615,4619,4620],{"id":2525,"depth":103,"text":2528},{"id":2557,"depth":103,"text":2560},{"id":2616,"depth":103,"text":2619,"children":4611},[4612,4613],{"id":2628,"depth":112,"text":2631},{"id":2789,"depth":112,"text":2792},{"id":3008,"depth":103,"text":3011},{"id":3603,"depth":103,"text":3606,"children":4616},[4617,4618],{"id":3614,"depth":112,"text":3617},{"id":3721,"depth":112,"text":3724},{"id":4435,"depth":103,"text":4438},{"id":4550,"depth":103,"text":4553},"content:blog:containerization-guide.md","blog/containerization-guide.md","blog/containerization-guide",{"_path":4625,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":4626,"description":4627,"slug":4628,"date":4629,"readTime":4630,"category":13,"image":4631,"imageCaption":4632,"author":4633,"tags":4635,"body":4640,"_type":1837,"_id":7402,"_source":1839,"_file":7403,"_stem":7404,"_extension":1842},"/blog/database-optimization","Database Performance Optimisation: How We Cut Query Time from 1200ms to 85ms","A deep-dive into the indexing strategies, query rewrites, and caching techniques that tripled throughput for a 50,000+ orders/day e-commerce platform—and the systematic process you can replicate.","database-optimization","2025-01-30","13 min","https://images.unsplash.com/photo-1544383835-bda2bc66a55d?w=1200&h=600&fit=crop&auto=format","Server infrastructure powering high-throughput database operations",{"name":17,"role":18,"avatar":19,"bio":20,"social":4634},{"github":22,"twitter":23,"linkedin":24},[4636,4637,29,4638,4639],"Databases","PostgreSQL","Optimisation","Scalability",{"type":31,"children":4641,"toc":7381},[4642,4648,4653,4658,4664,4669,4723,4931,4936,4942,4948,4953,5268,5273,5327,5333,5338,5470,5476,5481,5768,5774,5779,5785,5790,5834,5839,5865,5871,5876,6055,6075,6081,6086,6170,6175,6181,6186,6313,6318,6324,6329,6335,6872,6877,6883,6888,7152,7163,7169,7174,7269,7274,7280,7285,7372,7377],{"type":34,"tag":35,"props":4643,"children":4645},{"id":4644},"the-problem-no-one-sees-until-its-too-late",[4646],{"type":40,"value":4647},"The Problem No One Sees Until It's Too Late",{"type":34,"tag":43,"props":4649,"children":4650},{},[4651],{"type":40,"value":4652},"Database performance rarely degrades all at once. It creeps up gradually: a query that took 80ms at launch takes 300ms after six months of data growth, then 900ms a year later. By the time users notice slowness, the problem is already severe.",{"type":34,"tag":43,"props":4654,"children":4655},{},[4656],{"type":40,"value":4657},"We see this pattern repeatedly at MediaFront. The good news: most database performance issues stem from the same handful of root causes, and fixing them systematically delivers dramatic improvements without hardware upgrades.",{"type":34,"tag":35,"props":4659,"children":4661},{"id":4660},"start-with-measurement-not-guesses",[4662],{"type":40,"value":4663},"Start With Measurement, Not Guesses",{"type":34,"tag":43,"props":4665,"children":4666},{},[4667],{"type":40,"value":4668},"Every optimisation project begins the same way: instrument before you optimise. Guessing which query is slow wastes weeks. Your tools:",{"type":34,"tag":1762,"props":4670,"children":4671},{},[4672,4688,4713],{"type":34,"tag":1766,"props":4673,"children":4674},{},[4675,4679,4680,4686],{"type":34,"tag":1770,"props":4676,"children":4677},{},[4678],{"type":40,"value":4637},{"type":40,"value":2854},{"type":34,"tag":49,"props":4681,"children":4683},{"className":4682},[],[4684],{"type":40,"value":4685},"pg_stat_statements",{"type":40,"value":4687}," extension tracks cumulative query execution time across all calls",{"type":34,"tag":1766,"props":4689,"children":4690},{},[4691,4696,4698,4704,4705,4711],{"type":34,"tag":1770,"props":4692,"children":4693},{},[4694],{"type":40,"value":4695},"MySQL",{"type":40,"value":4697}," — the ",{"type":34,"tag":49,"props":4699,"children":4701},{"className":4700},[],[4702],{"type":40,"value":4703},"slow_query_log",{"type":40,"value":3592},{"type":34,"tag":49,"props":4706,"children":4708},{"className":4707},[],[4709],{"type":40,"value":4710},"long_query_time = 0.1",{"type":40,"value":4712}," captures everything above 100ms",{"type":34,"tag":1766,"props":4714,"children":4715},{},[4716,4721],{"type":34,"tag":1770,"props":4717,"children":4718},{},[4719],{"type":40,"value":4720},"SQL Server",{"type":40,"value":4722}," — Query Store provides a GUI over the same data",{"type":34,"tag":81,"props":4724,"children":4728},{"className":4725,"code":4726,"language":4727,"meta":7,"style":7},"language-sql shiki shiki-themes github-light","-- Find your 10 most expensive queries in PostgreSQL\nSELECT\n  query,\n  calls,\n  round(total_exec_time::numeric, 2) AS total_ms,\n  round(mean_exec_time::numeric, 2)  AS avg_ms,\n  round(stddev_exec_time::numeric, 2) AS stddev_ms\nFROM pg_stat_statements\nORDER BY total_exec_time DESC\nLIMIT 10;\n","sql",[4729],{"type":34,"tag":49,"props":4730,"children":4731},{"__ignoreMap":7},[4732,4740,4749,4757,4765,4807,4845,4882,4895,4913],{"type":34,"tag":91,"props":4733,"children":4734},{"class":93,"line":94},[4735],{"type":34,"tag":91,"props":4736,"children":4737},{"style":2895},[4738],{"type":40,"value":4739},"-- Find your 10 most expensive queries in PostgreSQL\n",{"type":34,"tag":91,"props":4741,"children":4742},{"class":93,"line":103},[4743],{"type":34,"tag":91,"props":4744,"children":4746},{"style":4745},"--shiki-default:#D73A49",[4747],{"type":40,"value":4748},"SELECT\n",{"type":34,"tag":91,"props":4750,"children":4751},{"class":93,"line":112},[4752],{"type":34,"tag":91,"props":4753,"children":4754},{"style":2904},[4755],{"type":40,"value":4756},"  query,\n",{"type":34,"tag":91,"props":4758,"children":4759},{"class":93,"line":121},[4760],{"type":34,"tag":91,"props":4761,"children":4762},{"style":2904},[4763],{"type":40,"value":4764},"  calls,\n",{"type":34,"tag":91,"props":4766,"children":4767},{"class":93,"line":131},[4768,4773,4778,4783,4787,4792,4797,4802],{"type":34,"tag":91,"props":4769,"children":4770},{"style":3305},[4771],{"type":40,"value":4772},"  round",{"type":34,"tag":91,"props":4774,"children":4775},{"style":2904},[4776],{"type":40,"value":4777},"(total_exec_time::",{"type":34,"tag":91,"props":4779,"children":4780},{"style":4745},[4781],{"type":40,"value":4782},"numeric",{"type":34,"tag":91,"props":4784,"children":4785},{"style":2904},[4786],{"type":40,"value":3229},{"type":34,"tag":91,"props":4788,"children":4789},{"style":3305},[4790],{"type":40,"value":4791},"2",{"type":34,"tag":91,"props":4793,"children":4794},{"style":2904},[4795],{"type":40,"value":4796},") ",{"type":34,"tag":91,"props":4798,"children":4799},{"style":4745},[4800],{"type":40,"value":4801},"AS",{"type":34,"tag":91,"props":4803,"children":4804},{"style":2904},[4805],{"type":40,"value":4806}," total_ms,\n",{"type":34,"tag":91,"props":4808,"children":4809},{"class":93,"line":140},[4810,4814,4819,4823,4827,4831,4836,4840],{"type":34,"tag":91,"props":4811,"children":4812},{"style":3305},[4813],{"type":40,"value":4772},{"type":34,"tag":91,"props":4815,"children":4816},{"style":2904},[4817],{"type":40,"value":4818},"(mean_exec_time::",{"type":34,"tag":91,"props":4820,"children":4821},{"style":4745},[4822],{"type":40,"value":4782},{"type":34,"tag":91,"props":4824,"children":4825},{"style":2904},[4826],{"type":40,"value":3229},{"type":34,"tag":91,"props":4828,"children":4829},{"style":3305},[4830],{"type":40,"value":4791},{"type":34,"tag":91,"props":4832,"children":4833},{"style":2904},[4834],{"type":40,"value":4835},")  ",{"type":34,"tag":91,"props":4837,"children":4838},{"style":4745},[4839],{"type":40,"value":4801},{"type":34,"tag":91,"props":4841,"children":4842},{"style":2904},[4843],{"type":40,"value":4844}," avg_ms,\n",{"type":34,"tag":91,"props":4846,"children":4847},{"class":93,"line":149},[4848,4852,4857,4861,4865,4869,4873,4877],{"type":34,"tag":91,"props":4849,"children":4850},{"style":3305},[4851],{"type":40,"value":4772},{"type":34,"tag":91,"props":4853,"children":4854},{"style":2904},[4855],{"type":40,"value":4856},"(stddev_exec_time::",{"type":34,"tag":91,"props":4858,"children":4859},{"style":4745},[4860],{"type":40,"value":4782},{"type":34,"tag":91,"props":4862,"children":4863},{"style":2904},[4864],{"type":40,"value":3229},{"type":34,"tag":91,"props":4866,"children":4867},{"style":3305},[4868],{"type":40,"value":4791},{"type":34,"tag":91,"props":4870,"children":4871},{"style":2904},[4872],{"type":40,"value":4796},{"type":34,"tag":91,"props":4874,"children":4875},{"style":4745},[4876],{"type":40,"value":4801},{"type":34,"tag":91,"props":4878,"children":4879},{"style":2904},[4880],{"type":40,"value":4881}," stddev_ms\n",{"type":34,"tag":91,"props":4883,"children":4884},{"class":93,"line":158},[4885,4890],{"type":34,"tag":91,"props":4886,"children":4887},{"style":4745},[4888],{"type":40,"value":4889},"FROM",{"type":34,"tag":91,"props":4891,"children":4892},{"style":2904},[4893],{"type":40,"value":4894}," pg_stat_statements\n",{"type":34,"tag":91,"props":4896,"children":4897},{"class":93,"line":167},[4898,4903,4908],{"type":34,"tag":91,"props":4899,"children":4900},{"style":4745},[4901],{"type":40,"value":4902},"ORDER BY",{"type":34,"tag":91,"props":4904,"children":4905},{"style":2904},[4906],{"type":40,"value":4907}," total_exec_time ",{"type":34,"tag":91,"props":4909,"children":4910},{"style":4745},[4911],{"type":40,"value":4912},"DESC\n",{"type":34,"tag":91,"props":4914,"children":4915},{"class":93,"line":176},[4916,4921,4926],{"type":34,"tag":91,"props":4917,"children":4918},{"style":4745},[4919],{"type":40,"value":4920},"LIMIT",{"type":34,"tag":91,"props":4922,"children":4923},{"style":3305},[4924],{"type":40,"value":4925}," 10",{"type":34,"tag":91,"props":4927,"children":4928},{"style":2904},[4929],{"type":40,"value":4930},";\n",{"type":34,"tag":43,"props":4932,"children":4933},{},[4934],{"type":40,"value":4935},"Fix the queries at the top of this list first. A 10× improvement on a query called 10,000 times per day is worth far more than a 100× improvement on one called 20 times.",{"type":34,"tag":35,"props":4937,"children":4939},{"id":4938},"query-optimisation-the-high-roi-fixes",[4940],{"type":40,"value":4941},"Query Optimisation: The High-ROI Fixes",{"type":34,"tag":2626,"props":4943,"children":4945},{"id":4944},"always-run-explain-analyze",[4946],{"type":40,"value":4947},"Always Run EXPLAIN ANALYZE",{"type":34,"tag":43,"props":4949,"children":4950},{},[4951],{"type":40,"value":4952},"Before touching an index or schema, understand how the database executes the query:",{"type":34,"tag":81,"props":4954,"children":4956},{"className":4725,"code":4955,"language":4727,"meta":7,"style":7},"EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)\nSELECT\n    c.customer_id,\n    c.name,\n    COUNT(o.order_id)     AS order_count,\n    SUM(o.total_amount)   AS total_spent\nFROM customers c\nLEFT JOIN orders o ON c.customer_id = o.customer_id\nWHERE c.signup_date > '2024-01-01'\nGROUP BY c.customer_id, c.name\nORDER BY total_spent DESC\nLIMIT 100;\n",[4957],{"type":34,"tag":49,"props":4958,"children":4959},{"__ignoreMap":7},[4960,4977,4984,5006,5025,5066,5105,5117,5167,5198,5236,5252],{"type":34,"tag":91,"props":4961,"children":4962},{"class":93,"line":94},[4963,4968,4973],{"type":34,"tag":91,"props":4964,"children":4965},{"style":2904},[4966],{"type":40,"value":4967},"EXPLAIN (ANALYZE, BUFFERS, FORMAT ",{"type":34,"tag":91,"props":4969,"children":4970},{"style":4745},[4971],{"type":40,"value":4972},"TEXT",{"type":34,"tag":91,"props":4974,"children":4975},{"style":2904},[4976],{"type":40,"value":477},{"type":34,"tag":91,"props":4978,"children":4979},{"class":93,"line":103},[4980],{"type":34,"tag":91,"props":4981,"children":4982},{"style":4745},[4983],{"type":40,"value":4748},{"type":34,"tag":91,"props":4985,"children":4986},{"class":93,"line":112},[4987,4992,4996,5001],{"type":34,"tag":91,"props":4988,"children":4989},{"style":3305},[4990],{"type":40,"value":4991},"    c",{"type":34,"tag":91,"props":4993,"children":4994},{"style":2904},[4995],{"type":40,"value":2549},{"type":34,"tag":91,"props":4997,"children":4998},{"style":3305},[4999],{"type":40,"value":5000},"customer_id",{"type":34,"tag":91,"props":5002,"children":5003},{"style":2904},[5004],{"type":40,"value":5005},",\n",{"type":34,"tag":91,"props":5007,"children":5008},{"class":93,"line":121},[5009,5013,5017,5021],{"type":34,"tag":91,"props":5010,"children":5011},{"style":3305},[5012],{"type":40,"value":4991},{"type":34,"tag":91,"props":5014,"children":5015},{"style":2904},[5016],{"type":40,"value":2549},{"type":34,"tag":91,"props":5018,"children":5019},{"style":3305},[5020],{"type":40,"value":2913},{"type":34,"tag":91,"props":5022,"children":5023},{"style":2904},[5024],{"type":40,"value":5005},{"type":34,"tag":91,"props":5026,"children":5027},{"class":93,"line":131},[5028,5033,5038,5043,5047,5052,5057,5061],{"type":34,"tag":91,"props":5029,"children":5030},{"style":3305},[5031],{"type":40,"value":5032},"    COUNT",{"type":34,"tag":91,"props":5034,"children":5035},{"style":2904},[5036],{"type":40,"value":5037},"(",{"type":34,"tag":91,"props":5039,"children":5040},{"style":3305},[5041],{"type":40,"value":5042},"o",{"type":34,"tag":91,"props":5044,"children":5045},{"style":2904},[5046],{"type":40,"value":2549},{"type":34,"tag":91,"props":5048,"children":5049},{"style":3305},[5050],{"type":40,"value":5051},"order_id",{"type":34,"tag":91,"props":5053,"children":5054},{"style":2904},[5055],{"type":40,"value":5056},")     ",{"type":34,"tag":91,"props":5058,"children":5059},{"style":4745},[5060],{"type":40,"value":4801},{"type":34,"tag":91,"props":5062,"children":5063},{"style":2904},[5064],{"type":40,"value":5065}," order_count,\n",{"type":34,"tag":91,"props":5067,"children":5068},{"class":93,"line":140},[5069,5074,5078,5082,5086,5091,5096,5100],{"type":34,"tag":91,"props":5070,"children":5071},{"style":3305},[5072],{"type":40,"value":5073},"    SUM",{"type":34,"tag":91,"props":5075,"children":5076},{"style":2904},[5077],{"type":40,"value":5037},{"type":34,"tag":91,"props":5079,"children":5080},{"style":3305},[5081],{"type":40,"value":5042},{"type":34,"tag":91,"props":5083,"children":5084},{"style":2904},[5085],{"type":40,"value":2549},{"type":34,"tag":91,"props":5087,"children":5088},{"style":3305},[5089],{"type":40,"value":5090},"total_amount",{"type":34,"tag":91,"props":5092,"children":5093},{"style":2904},[5094],{"type":40,"value":5095},")   ",{"type":34,"tag":91,"props":5097,"children":5098},{"style":4745},[5099],{"type":40,"value":4801},{"type":34,"tag":91,"props":5101,"children":5102},{"style":2904},[5103],{"type":40,"value":5104}," total_spent\n",{"type":34,"tag":91,"props":5106,"children":5107},{"class":93,"line":149},[5108,5112],{"type":34,"tag":91,"props":5109,"children":5110},{"style":4745},[5111],{"type":40,"value":4889},{"type":34,"tag":91,"props":5113,"children":5114},{"style":2904},[5115],{"type":40,"value":5116}," customers c\n",{"type":34,"tag":91,"props":5118,"children":5119},{"class":93,"line":158},[5120,5125,5130,5135,5140,5144,5148,5153,5158,5162],{"type":34,"tag":91,"props":5121,"children":5122},{"style":4745},[5123],{"type":40,"value":5124},"LEFT JOIN",{"type":34,"tag":91,"props":5126,"children":5127},{"style":2904},[5128],{"type":40,"value":5129}," orders o ",{"type":34,"tag":91,"props":5131,"children":5132},{"style":4745},[5133],{"type":40,"value":5134},"ON",{"type":34,"tag":91,"props":5136,"children":5137},{"style":3305},[5138],{"type":40,"value":5139}," c",{"type":34,"tag":91,"props":5141,"children":5142},{"style":2904},[5143],{"type":40,"value":2549},{"type":34,"tag":91,"props":5145,"children":5146},{"style":3305},[5147],{"type":40,"value":5000},{"type":34,"tag":91,"props":5149,"children":5150},{"style":4745},[5151],{"type":40,"value":5152}," =",{"type":34,"tag":91,"props":5154,"children":5155},{"style":3305},[5156],{"type":40,"value":5157}," o",{"type":34,"tag":91,"props":5159,"children":5160},{"style":2904},[5161],{"type":40,"value":2549},{"type":34,"tag":91,"props":5163,"children":5164},{"style":3305},[5165],{"type":40,"value":5166},"customer_id\n",{"type":34,"tag":91,"props":5168,"children":5169},{"class":93,"line":167},[5170,5175,5179,5183,5188,5193],{"type":34,"tag":91,"props":5171,"children":5172},{"style":4745},[5173],{"type":40,"value":5174},"WHERE",{"type":34,"tag":91,"props":5176,"children":5177},{"style":3305},[5178],{"type":40,"value":5139},{"type":34,"tag":91,"props":5180,"children":5181},{"style":2904},[5182],{"type":40,"value":2549},{"type":34,"tag":91,"props":5184,"children":5185},{"style":3305},[5186],{"type":40,"value":5187},"signup_date",{"type":34,"tag":91,"props":5189,"children":5190},{"style":4745},[5191],{"type":40,"value":5192}," >",{"type":34,"tag":91,"props":5194,"children":5195},{"style":2921},[5196],{"type":40,"value":5197}," '2024-01-01'\n",{"type":34,"tag":91,"props":5199,"children":5200},{"class":93,"line":176},[5201,5206,5210,5214,5218,5222,5227,5231],{"type":34,"tag":91,"props":5202,"children":5203},{"style":4745},[5204],{"type":40,"value":5205},"GROUP BY",{"type":34,"tag":91,"props":5207,"children":5208},{"style":3305},[5209],{"type":40,"value":5139},{"type":34,"tag":91,"props":5211,"children":5212},{"style":2904},[5213],{"type":40,"value":2549},{"type":34,"tag":91,"props":5215,"children":5216},{"style":3305},[5217],{"type":40,"value":5000},{"type":34,"tag":91,"props":5219,"children":5220},{"style":2904},[5221],{"type":40,"value":3229},{"type":34,"tag":91,"props":5223,"children":5224},{"style":3305},[5225],{"type":40,"value":5226},"c",{"type":34,"tag":91,"props":5228,"children":5229},{"style":2904},[5230],{"type":40,"value":2549},{"type":34,"tag":91,"props":5232,"children":5233},{"style":3305},[5234],{"type":40,"value":5235},"name\n",{"type":34,"tag":91,"props":5237,"children":5238},{"class":93,"line":184},[5239,5243,5248],{"type":34,"tag":91,"props":5240,"children":5241},{"style":4745},[5242],{"type":40,"value":4902},{"type":34,"tag":91,"props":5244,"children":5245},{"style":2904},[5246],{"type":40,"value":5247}," total_spent ",{"type":34,"tag":91,"props":5249,"children":5250},{"style":4745},[5251],{"type":40,"value":4912},{"type":34,"tag":91,"props":5253,"children":5254},{"class":93,"line":193},[5255,5259,5264],{"type":34,"tag":91,"props":5256,"children":5257},{"style":4745},[5258],{"type":40,"value":4920},{"type":34,"tag":91,"props":5260,"children":5261},{"style":3305},[5262],{"type":40,"value":5263}," 100",{"type":34,"tag":91,"props":5265,"children":5266},{"style":2904},[5267],{"type":40,"value":4930},{"type":34,"tag":43,"props":5269,"children":5270},{},[5271],{"type":40,"value":5272},"Red flags in the output:",{"type":34,"tag":1762,"props":5274,"children":5275},{},[5276,5287,5314],{"type":34,"tag":1766,"props":5277,"children":5278},{},[5279,5285],{"type":34,"tag":49,"props":5280,"children":5282},{"className":5281},[],[5283],{"type":40,"value":5284},"Seq Scan",{"type":40,"value":5286}," on a large table — almost always an index opportunity",{"type":34,"tag":1766,"props":5288,"children":5289},{},[5290,5296,5298,5304,5306,5312],{"type":34,"tag":49,"props":5291,"children":5293},{"className":5292},[],[5294],{"type":40,"value":5295},"Hash Join",{"type":40,"value":5297}," with large ",{"type":34,"tag":49,"props":5299,"children":5301},{"className":5300},[],[5302],{"type":40,"value":5303},"Batches",{"type":40,"value":5305}," — memory pressure, increase ",{"type":34,"tag":49,"props":5307,"children":5309},{"className":5308},[],[5310],{"type":40,"value":5311},"work_mem",{"type":40,"value":5313}," or add an index",{"type":34,"tag":1766,"props":5315,"children":5316},{},[5317,5319,5325],{"type":40,"value":5318},"High ",{"type":34,"tag":49,"props":5320,"children":5322},{"className":5321},[],[5323],{"type":40,"value":5324},"Buffers: shared read",{"type":40,"value":5326}," — data not in cache, consider a covering index",{"type":34,"tag":2626,"props":5328,"children":5330},{"id":5329},"stop-using-select",[5331],{"type":40,"value":5332},"Stop Using SELECT *",{"type":34,"tag":43,"props":5334,"children":5335},{},[5336],{"type":40,"value":5337},"This single habit kills performance in multiple ways: it fetches columns you'll never use, prevents covering-index optimisation, and bloats network payloads.",{"type":34,"tag":81,"props":5339,"children":5341},{"className":4725,"code":5340,"language":4727,"meta":7,"style":7},"-- ❌ Fetches all 22 columns including large TEXT fields\nSELECT * FROM products WHERE category_id = 5;\n\n-- ✅ Fetches exactly what the UI renders\nSELECT product_id, name, price, stock_qty\nFROM products\nWHERE category_id = 5;\n",[5342],{"type":34,"tag":49,"props":5343,"children":5344},{"__ignoreMap":7},[5345,5353,5399,5406,5414,5435,5447],{"type":34,"tag":91,"props":5346,"children":5347},{"class":93,"line":94},[5348],{"type":34,"tag":91,"props":5349,"children":5350},{"style":2895},[5351],{"type":40,"value":5352},"-- ❌ Fetches all 22 columns including large TEXT fields\n",{"type":34,"tag":91,"props":5354,"children":5355},{"class":93,"line":103},[5356,5361,5366,5371,5376,5380,5385,5390,5395],{"type":34,"tag":91,"props":5357,"children":5358},{"style":4745},[5359],{"type":40,"value":5360},"SELECT",{"type":34,"tag":91,"props":5362,"children":5363},{"style":4745},[5364],{"type":40,"value":5365}," *",{"type":34,"tag":91,"props":5367,"children":5368},{"style":4745},[5369],{"type":40,"value":5370}," FROM",{"type":34,"tag":91,"props":5372,"children":5373},{"style":2904},[5374],{"type":40,"value":5375}," products ",{"type":34,"tag":91,"props":5377,"children":5378},{"style":4745},[5379],{"type":40,"value":5174},{"type":34,"tag":91,"props":5381,"children":5382},{"style":2904},[5383],{"type":40,"value":5384}," category_id ",{"type":34,"tag":91,"props":5386,"children":5387},{"style":4745},[5388],{"type":40,"value":5389},"=",{"type":34,"tag":91,"props":5391,"children":5392},{"style":3305},[5393],{"type":40,"value":5394}," 5",{"type":34,"tag":91,"props":5396,"children":5397},{"style":2904},[5398],{"type":40,"value":4930},{"type":34,"tag":91,"props":5400,"children":5401},{"class":93,"line":112},[5402],{"type":34,"tag":91,"props":5403,"children":5404},{"emptyLinePlaceholder":125},[5405],{"type":40,"value":128},{"type":34,"tag":91,"props":5407,"children":5408},{"class":93,"line":121},[5409],{"type":34,"tag":91,"props":5410,"children":5411},{"style":2895},[5412],{"type":40,"value":5413},"-- ✅ Fetches exactly what the UI renders\n",{"type":34,"tag":91,"props":5415,"children":5416},{"class":93,"line":131},[5417,5421,5426,5430],{"type":34,"tag":91,"props":5418,"children":5419},{"style":4745},[5420],{"type":40,"value":5360},{"type":34,"tag":91,"props":5422,"children":5423},{"style":2904},[5424],{"type":40,"value":5425}," product_id, ",{"type":34,"tag":91,"props":5427,"children":5428},{"style":4745},[5429],{"type":40,"value":2913},{"type":34,"tag":91,"props":5431,"children":5432},{"style":2904},[5433],{"type":40,"value":5434},", price, stock_qty\n",{"type":34,"tag":91,"props":5436,"children":5437},{"class":93,"line":140},[5438,5442],{"type":34,"tag":91,"props":5439,"children":5440},{"style":4745},[5441],{"type":40,"value":4889},{"type":34,"tag":91,"props":5443,"children":5444},{"style":2904},[5445],{"type":40,"value":5446}," products\n",{"type":34,"tag":91,"props":5448,"children":5449},{"class":93,"line":149},[5450,5454,5458,5462,5466],{"type":34,"tag":91,"props":5451,"children":5452},{"style":4745},[5453],{"type":40,"value":5174},{"type":34,"tag":91,"props":5455,"children":5456},{"style":2904},[5457],{"type":40,"value":5384},{"type":34,"tag":91,"props":5459,"children":5460},{"style":4745},[5461],{"type":40,"value":5389},{"type":34,"tag":91,"props":5463,"children":5464},{"style":3305},[5465],{"type":40,"value":5394},{"type":34,"tag":91,"props":5467,"children":5468},{"style":2904},[5469],{"type":40,"value":4930},{"type":34,"tag":2626,"props":5471,"children":5473},{"id":5472},"rewrite-correlated-subqueries-as-joins",[5474],{"type":40,"value":5475},"Rewrite Correlated Subqueries as Joins",{"type":34,"tag":43,"props":5477,"children":5478},{},[5479],{"type":40,"value":5480},"Correlated subqueries execute once per row of the outer query. On a table with 500,000 rows, a correlated subquery that takes 0.5ms runs for 250 seconds total.",{"type":34,"tag":81,"props":5482,"children":5484},{"className":4725,"code":5483,"language":4727,"meta":7,"style":7},"-- ❌ Correlated subquery — O(n) database calls\nSELECT name,\n  (SELECT MAX(order_date) FROM orders WHERE customer_id = c.id) AS last_order\nFROM customers c;\n\n-- ✅ Single-pass join\nSELECT c.name, o.last_order\nFROM customers c\nLEFT JOIN (\n  SELECT customer_id, MAX(order_date) AS last_order\n  FROM orders\n  GROUP BY customer_id\n) o ON c.id = o.customer_id;\n",[5485],{"type":34,"tag":49,"props":5486,"children":5487},{"__ignoreMap":7},[5488,5496,5512,5582,5594,5601,5609,5645,5656,5668,5698,5711,5724],{"type":34,"tag":91,"props":5489,"children":5490},{"class":93,"line":94},[5491],{"type":34,"tag":91,"props":5492,"children":5493},{"style":2895},[5494],{"type":40,"value":5495},"-- ❌ Correlated subquery — O(n) database calls\n",{"type":34,"tag":91,"props":5497,"children":5498},{"class":93,"line":103},[5499,5503,5508],{"type":34,"tag":91,"props":5500,"children":5501},{"style":4745},[5502],{"type":40,"value":5360},{"type":34,"tag":91,"props":5504,"children":5505},{"style":4745},[5506],{"type":40,"value":5507}," name",{"type":34,"tag":91,"props":5509,"children":5510},{"style":2904},[5511],{"type":40,"value":5005},{"type":34,"tag":91,"props":5513,"children":5514},{"class":93,"line":112},[5515,5520,5524,5529,5534,5538,5543,5547,5552,5556,5560,5564,5569,5573,5577],{"type":34,"tag":91,"props":5516,"children":5517},{"style":2904},[5518],{"type":40,"value":5519},"  (",{"type":34,"tag":91,"props":5521,"children":5522},{"style":4745},[5523],{"type":40,"value":5360},{"type":34,"tag":91,"props":5525,"children":5526},{"style":3305},[5527],{"type":40,"value":5528}," MAX",{"type":34,"tag":91,"props":5530,"children":5531},{"style":2904},[5532],{"type":40,"value":5533},"(order_date) ",{"type":34,"tag":91,"props":5535,"children":5536},{"style":4745},[5537],{"type":40,"value":4889},{"type":34,"tag":91,"props":5539,"children":5540},{"style":2904},[5541],{"type":40,"value":5542}," orders ",{"type":34,"tag":91,"props":5544,"children":5545},{"style":4745},[5546],{"type":40,"value":5174},{"type":34,"tag":91,"props":5548,"children":5549},{"style":2904},[5550],{"type":40,"value":5551}," customer_id ",{"type":34,"tag":91,"props":5553,"children":5554},{"style":4745},[5555],{"type":40,"value":5389},{"type":34,"tag":91,"props":5557,"children":5558},{"style":3305},[5559],{"type":40,"value":5139},{"type":34,"tag":91,"props":5561,"children":5562},{"style":2904},[5563],{"type":40,"value":2549},{"type":34,"tag":91,"props":5565,"children":5566},{"style":3305},[5567],{"type":40,"value":5568},"id",{"type":34,"tag":91,"props":5570,"children":5571},{"style":2904},[5572],{"type":40,"value":4796},{"type":34,"tag":91,"props":5574,"children":5575},{"style":4745},[5576],{"type":40,"value":4801},{"type":34,"tag":91,"props":5578,"children":5579},{"style":2904},[5580],{"type":40,"value":5581}," last_order\n",{"type":34,"tag":91,"props":5583,"children":5584},{"class":93,"line":121},[5585,5589],{"type":34,"tag":91,"props":5586,"children":5587},{"style":4745},[5588],{"type":40,"value":4889},{"type":34,"tag":91,"props":5590,"children":5591},{"style":2904},[5592],{"type":40,"value":5593}," customers c;\n",{"type":34,"tag":91,"props":5595,"children":5596},{"class":93,"line":131},[5597],{"type":34,"tag":91,"props":5598,"children":5599},{"emptyLinePlaceholder":125},[5600],{"type":40,"value":128},{"type":34,"tag":91,"props":5602,"children":5603},{"class":93,"line":140},[5604],{"type":34,"tag":91,"props":5605,"children":5606},{"style":2895},[5607],{"type":40,"value":5608},"-- ✅ Single-pass join\n",{"type":34,"tag":91,"props":5610,"children":5611},{"class":93,"line":149},[5612,5616,5620,5624,5628,5632,5636,5640],{"type":34,"tag":91,"props":5613,"children":5614},{"style":4745},[5615],{"type":40,"value":5360},{"type":34,"tag":91,"props":5617,"children":5618},{"style":3305},[5619],{"type":40,"value":5139},{"type":34,"tag":91,"props":5621,"children":5622},{"style":2904},[5623],{"type":40,"value":2549},{"type":34,"tag":91,"props":5625,"children":5626},{"style":3305},[5627],{"type":40,"value":2913},{"type":34,"tag":91,"props":5629,"children":5630},{"style":2904},[5631],{"type":40,"value":3229},{"type":34,"tag":91,"props":5633,"children":5634},{"style":3305},[5635],{"type":40,"value":5042},{"type":34,"tag":91,"props":5637,"children":5638},{"style":2904},[5639],{"type":40,"value":2549},{"type":34,"tag":91,"props":5641,"children":5642},{"style":3305},[5643],{"type":40,"value":5644},"last_order\n",{"type":34,"tag":91,"props":5646,"children":5647},{"class":93,"line":158},[5648,5652],{"type":34,"tag":91,"props":5649,"children":5650},{"style":4745},[5651],{"type":40,"value":4889},{"type":34,"tag":91,"props":5653,"children":5654},{"style":2904},[5655],{"type":40,"value":5116},{"type":34,"tag":91,"props":5657,"children":5658},{"class":93,"line":167},[5659,5663],{"type":34,"tag":91,"props":5660,"children":5661},{"style":4745},[5662],{"type":40,"value":5124},{"type":34,"tag":91,"props":5664,"children":5665},{"style":2904},[5666],{"type":40,"value":5667}," (\n",{"type":34,"tag":91,"props":5669,"children":5670},{"class":93,"line":176},[5671,5676,5681,5686,5690,5694],{"type":34,"tag":91,"props":5672,"children":5673},{"style":4745},[5674],{"type":40,"value":5675},"  SELECT",{"type":34,"tag":91,"props":5677,"children":5678},{"style":2904},[5679],{"type":40,"value":5680}," customer_id, ",{"type":34,"tag":91,"props":5682,"children":5683},{"style":3305},[5684],{"type":40,"value":5685},"MAX",{"type":34,"tag":91,"props":5687,"children":5688},{"style":2904},[5689],{"type":40,"value":5533},{"type":34,"tag":91,"props":5691,"children":5692},{"style":4745},[5693],{"type":40,"value":4801},{"type":34,"tag":91,"props":5695,"children":5696},{"style":2904},[5697],{"type":40,"value":5581},{"type":34,"tag":91,"props":5699,"children":5700},{"class":93,"line":184},[5701,5706],{"type":34,"tag":91,"props":5702,"children":5703},{"style":4745},[5704],{"type":40,"value":5705},"  FROM",{"type":34,"tag":91,"props":5707,"children":5708},{"style":2904},[5709],{"type":40,"value":5710}," orders\n",{"type":34,"tag":91,"props":5712,"children":5713},{"class":93,"line":193},[5714,5719],{"type":34,"tag":91,"props":5715,"children":5716},{"style":4745},[5717],{"type":40,"value":5718},"  GROUP BY",{"type":34,"tag":91,"props":5720,"children":5721},{"style":2904},[5722],{"type":40,"value":5723}," customer_id\n",{"type":34,"tag":91,"props":5725,"children":5726},{"class":93,"line":202},[5727,5732,5736,5740,5744,5748,5752,5756,5760,5764],{"type":34,"tag":91,"props":5728,"children":5729},{"style":2904},[5730],{"type":40,"value":5731},") o ",{"type":34,"tag":91,"props":5733,"children":5734},{"style":4745},[5735],{"type":40,"value":5134},{"type":34,"tag":91,"props":5737,"children":5738},{"style":3305},[5739],{"type":40,"value":5139},{"type":34,"tag":91,"props":5741,"children":5742},{"style":2904},[5743],{"type":40,"value":2549},{"type":34,"tag":91,"props":5745,"children":5746},{"style":3305},[5747],{"type":40,"value":5568},{"type":34,"tag":91,"props":5749,"children":5750},{"style":4745},[5751],{"type":40,"value":5152},{"type":34,"tag":91,"props":5753,"children":5754},{"style":3305},[5755],{"type":40,"value":5157},{"type":34,"tag":91,"props":5757,"children":5758},{"style":2904},[5759],{"type":40,"value":2549},{"type":34,"tag":91,"props":5761,"children":5762},{"style":3305},[5763],{"type":40,"value":5000},{"type":34,"tag":91,"props":5765,"children":5766},{"style":2904},[5767],{"type":40,"value":4930},{"type":34,"tag":35,"props":5769,"children":5771},{"id":5770},"indexing-strategy",[5772],{"type":40,"value":5773},"Indexing Strategy",{"type":34,"tag":43,"props":5775,"children":5776},{},[5777],{"type":40,"value":5778},"Indexes are the single highest-leverage tool in your optimisation arsenal—but only when used intentionally.",{"type":34,"tag":2626,"props":5780,"children":5782},{"id":5781},"the-index-decision-framework",[5783],{"type":40,"value":5784},"The Index Decision Framework",{"type":34,"tag":43,"props":5786,"children":5787},{},[5788],{"type":40,"value":5789},"Create an index when:",{"type":34,"tag":2129,"props":5791,"children":5792},{},[5793,5819,5824,5829],{"type":34,"tag":1766,"props":5794,"children":5795},{},[5796,5798,5803,5804,5810,5812,5817],{"type":40,"value":5797},"The column appears in a ",{"type":34,"tag":49,"props":5799,"children":5801},{"className":5800},[],[5802],{"type":40,"value":5174},{"type":40,"value":3229},{"type":34,"tag":49,"props":5805,"children":5807},{"className":5806},[],[5808],{"type":40,"value":5809},"JOIN ON",{"type":40,"value":5811},", or ",{"type":34,"tag":49,"props":5813,"children":5815},{"className":5814},[],[5816],{"type":40,"value":4902},{"type":40,"value":5818}," clause",{"type":34,"tag":1766,"props":5820,"children":5821},{},[5822],{"type":40,"value":5823},"The column has high cardinality (many distinct values)",{"type":34,"tag":1766,"props":5825,"children":5826},{},[5827],{"type":40,"value":5828},"The table has more than ~10,000 rows",{"type":34,"tag":1766,"props":5830,"children":5831},{},[5832],{"type":40,"value":5833},"The read/write ratio for this table favours reads",{"type":34,"tag":43,"props":5835,"children":5836},{},[5837],{"type":40,"value":5838},"Avoid indexes when:",{"type":34,"tag":1762,"props":5840,"children":5841},{},[5842,5847,5860],{"type":34,"tag":1766,"props":5843,"children":5844},{},[5845],{"type":40,"value":5846},"The table is write-heavy (each index slows every INSERT/UPDATE/DELETE)",{"type":34,"tag":1766,"props":5848,"children":5849},{},[5850,5852,5858],{"type":40,"value":5851},"The column has very low cardinality (e.g., a boolean ",{"type":34,"tag":49,"props":5853,"children":5855},{"className":5854},[],[5856],{"type":40,"value":5857},"is_active",{"type":40,"value":5859},")",{"type":34,"tag":1766,"props":5861,"children":5862},{},[5863],{"type":40,"value":5864},"The query planner already uses a more selective index",{"type":34,"tag":2626,"props":5866,"children":5868},{"id":5867},"covering-indexes-eliminate-table-lookups",[5869],{"type":40,"value":5870},"Covering Indexes Eliminate Table Lookups",{"type":34,"tag":43,"props":5872,"children":5873},{},[5874],{"type":40,"value":5875},"A covering index includes all columns a query needs, so PostgreSQL never touches the main table:",{"type":34,"tag":81,"props":5877,"children":5879},{"className":4725,"code":5878,"language":4727,"meta":7,"style":7},"-- Query: find a customer's recent orders by status\nSELECT order_id, order_date, total_amount\nFROM orders\nWHERE customer_id = 12345\n  AND status = 'pending'\nORDER BY order_date DESC;\n\n-- Covering index — all queried columns live in the index\nCREATE INDEX idx_orders_customer_status_date_amount\n  ON orders (customer_id, status, order_date DESC)\n  INCLUDE (total_amount);\n",[5880],{"type":34,"tag":49,"props":5881,"children":5882},{"__ignoreMap":7},[5883,5891,5903,5914,5934,5956,5977,5984,5992,6011,6042],{"type":34,"tag":91,"props":5884,"children":5885},{"class":93,"line":94},[5886],{"type":34,"tag":91,"props":5887,"children":5888},{"style":2895},[5889],{"type":40,"value":5890},"-- Query: find a customer's recent orders by status\n",{"type":34,"tag":91,"props":5892,"children":5893},{"class":93,"line":103},[5894,5898],{"type":34,"tag":91,"props":5895,"children":5896},{"style":4745},[5897],{"type":40,"value":5360},{"type":34,"tag":91,"props":5899,"children":5900},{"style":2904},[5901],{"type":40,"value":5902}," order_id, order_date, total_amount\n",{"type":34,"tag":91,"props":5904,"children":5905},{"class":93,"line":112},[5906,5910],{"type":34,"tag":91,"props":5907,"children":5908},{"style":4745},[5909],{"type":40,"value":4889},{"type":34,"tag":91,"props":5911,"children":5912},{"style":2904},[5913],{"type":40,"value":5710},{"type":34,"tag":91,"props":5915,"children":5916},{"class":93,"line":121},[5917,5921,5925,5929],{"type":34,"tag":91,"props":5918,"children":5919},{"style":4745},[5920],{"type":40,"value":5174},{"type":34,"tag":91,"props":5922,"children":5923},{"style":2904},[5924],{"type":40,"value":5551},{"type":34,"tag":91,"props":5926,"children":5927},{"style":4745},[5928],{"type":40,"value":5389},{"type":34,"tag":91,"props":5930,"children":5931},{"style":3305},[5932],{"type":40,"value":5933}," 12345\n",{"type":34,"tag":91,"props":5935,"children":5936},{"class":93,"line":131},[5937,5942,5947,5951],{"type":34,"tag":91,"props":5938,"children":5939},{"style":4745},[5940],{"type":40,"value":5941},"  AND",{"type":34,"tag":91,"props":5943,"children":5944},{"style":4745},[5945],{"type":40,"value":5946}," status",{"type":34,"tag":91,"props":5948,"children":5949},{"style":4745},[5950],{"type":40,"value":5152},{"type":34,"tag":91,"props":5952,"children":5953},{"style":2921},[5954],{"type":40,"value":5955}," 'pending'\n",{"type":34,"tag":91,"props":5957,"children":5958},{"class":93,"line":140},[5959,5963,5968,5973],{"type":34,"tag":91,"props":5960,"children":5961},{"style":4745},[5962],{"type":40,"value":4902},{"type":34,"tag":91,"props":5964,"children":5965},{"style":2904},[5966],{"type":40,"value":5967}," order_date ",{"type":34,"tag":91,"props":5969,"children":5970},{"style":4745},[5971],{"type":40,"value":5972},"DESC",{"type":34,"tag":91,"props":5974,"children":5975},{"style":2904},[5976],{"type":40,"value":4930},{"type":34,"tag":91,"props":5978,"children":5979},{"class":93,"line":149},[5980],{"type":34,"tag":91,"props":5981,"children":5982},{"emptyLinePlaceholder":125},[5983],{"type":40,"value":128},{"type":34,"tag":91,"props":5985,"children":5986},{"class":93,"line":158},[5987],{"type":34,"tag":91,"props":5988,"children":5989},{"style":2895},[5990],{"type":40,"value":5991},"-- Covering index — all queried columns live in the index\n",{"type":34,"tag":91,"props":5993,"children":5994},{"class":93,"line":167},[5995,6000,6005],{"type":34,"tag":91,"props":5996,"children":5997},{"style":4745},[5998],{"type":40,"value":5999},"CREATE",{"type":34,"tag":91,"props":6001,"children":6002},{"style":4745},[6003],{"type":40,"value":6004}," INDEX",{"type":34,"tag":91,"props":6006,"children":6008},{"style":6007},"--shiki-default:#6F42C1",[6009],{"type":40,"value":6010}," idx_orders_customer_status_date_amount\n",{"type":34,"tag":91,"props":6012,"children":6013},{"class":93,"line":176},[6014,6019,6024,6029,6034,6038],{"type":34,"tag":91,"props":6015,"children":6016},{"style":4745},[6017],{"type":40,"value":6018},"  ON",{"type":34,"tag":91,"props":6020,"children":6021},{"style":2904},[6022],{"type":40,"value":6023}," orders (customer_id, ",{"type":34,"tag":91,"props":6025,"children":6026},{"style":4745},[6027],{"type":40,"value":6028},"status",{"type":34,"tag":91,"props":6030,"children":6031},{"style":2904},[6032],{"type":40,"value":6033},", order_date ",{"type":34,"tag":91,"props":6035,"children":6036},{"style":4745},[6037],{"type":40,"value":5972},{"type":34,"tag":91,"props":6039,"children":6040},{"style":2904},[6041],{"type":40,"value":477},{"type":34,"tag":91,"props":6043,"children":6044},{"class":93,"line":184},[6045,6050],{"type":34,"tag":91,"props":6046,"children":6047},{"style":4745},[6048],{"type":40,"value":6049},"  INCLUDE",{"type":34,"tag":91,"props":6051,"children":6052},{"style":2904},[6053],{"type":40,"value":6054}," (total_amount);\n",{"type":34,"tag":43,"props":6056,"children":6057},{},[6058,6060,6066,6068,6073],{"type":40,"value":6059},"The ",{"type":34,"tag":49,"props":6061,"children":6063},{"className":6062},[],[6064],{"type":40,"value":6065},"INCLUDE",{"type":40,"value":6067}," clause (PostgreSQL 11+) adds ",{"type":34,"tag":49,"props":6069,"children":6071},{"className":6070},[],[6072],{"type":40,"value":5090},{"type":40,"value":6074}," to leaf pages without affecting sort order, making this a true zero-heap-access query.",{"type":34,"tag":2626,"props":6076,"children":6078},{"id":6077},"partial-indexes-for-selective-conditions",[6079],{"type":40,"value":6080},"Partial Indexes for Selective Conditions",{"type":34,"tag":43,"props":6082,"children":6083},{},[6084],{"type":40,"value":6085},"When you only ever query a subset of rows, index only that subset:",{"type":34,"tag":81,"props":6087,"children":6089},{"className":4725,"code":6088,"language":4727,"meta":7,"style":7},"-- Only active, unfulfilled orders matter for the operations dashboard\nCREATE INDEX idx_orders_unfulfilled\n  ON orders (customer_id, created_at)\n  WHERE status IN ('pending', 'processing');\n",[6090],{"type":34,"tag":49,"props":6091,"children":6092},{"__ignoreMap":7},[6093,6101,6117,6129],{"type":34,"tag":91,"props":6094,"children":6095},{"class":93,"line":94},[6096],{"type":34,"tag":91,"props":6097,"children":6098},{"style":2895},[6099],{"type":40,"value":6100},"-- Only active, unfulfilled orders matter for the operations dashboard\n",{"type":34,"tag":91,"props":6102,"children":6103},{"class":93,"line":103},[6104,6108,6112],{"type":34,"tag":91,"props":6105,"children":6106},{"style":4745},[6107],{"type":40,"value":5999},{"type":34,"tag":91,"props":6109,"children":6110},{"style":4745},[6111],{"type":40,"value":6004},{"type":34,"tag":91,"props":6113,"children":6114},{"style":6007},[6115],{"type":40,"value":6116}," idx_orders_unfulfilled\n",{"type":34,"tag":91,"props":6118,"children":6119},{"class":93,"line":112},[6120,6124],{"type":34,"tag":91,"props":6121,"children":6122},{"style":4745},[6123],{"type":40,"value":6018},{"type":34,"tag":91,"props":6125,"children":6126},{"style":2904},[6127],{"type":40,"value":6128}," orders (customer_id, created_at)\n",{"type":34,"tag":91,"props":6130,"children":6131},{"class":93,"line":121},[6132,6137,6141,6146,6151,6156,6160,6165],{"type":34,"tag":91,"props":6133,"children":6134},{"style":4745},[6135],{"type":40,"value":6136},"  WHERE",{"type":34,"tag":91,"props":6138,"children":6139},{"style":4745},[6140],{"type":40,"value":5946},{"type":34,"tag":91,"props":6142,"children":6143},{"style":4745},[6144],{"type":40,"value":6145}," IN",{"type":34,"tag":91,"props":6147,"children":6148},{"style":2904},[6149],{"type":40,"value":6150}," (",{"type":34,"tag":91,"props":6152,"children":6153},{"style":2921},[6154],{"type":40,"value":6155},"'pending'",{"type":34,"tag":91,"props":6157,"children":6158},{"style":2904},[6159],{"type":40,"value":3229},{"type":34,"tag":91,"props":6161,"children":6162},{"style":2921},[6163],{"type":40,"value":6164},"'processing'",{"type":34,"tag":91,"props":6166,"children":6167},{"style":2904},[6168],{"type":40,"value":6169},");\n",{"type":34,"tag":43,"props":6171,"children":6172},{},[6173],{"type":40,"value":6174},"This index is a fraction of the size of a full index on those columns, making it faster to build, cheaper to maintain, and more likely to stay in memory.",{"type":34,"tag":2626,"props":6176,"children":6178},{"id":6177},"prune-dead-indexes",[6179],{"type":40,"value":6180},"Prune Dead Indexes",{"type":34,"tag":43,"props":6182,"children":6183},{},[6184],{"type":40,"value":6185},"Unused indexes are pure cost: they consume disk, slow writes, and confuse the planner. Find them:",{"type":34,"tag":81,"props":6187,"children":6189},{"className":4725,"code":6188,"language":4727,"meta":7,"style":7},"SELECT\n  schemaname,\n  tablename,\n  indexname,\n  idx_scan AS scans_since_restart\nFROM pg_stat_user_indexes\nWHERE idx_scan = 0\n  AND indexrelname NOT LIKE '%_pkey'\nORDER BY schemaname, tablename;\n",[6190],{"type":34,"tag":49,"props":6191,"children":6192},{"__ignoreMap":7},[6193,6200,6208,6216,6224,6241,6253,6274,6301],{"type":34,"tag":91,"props":6194,"children":6195},{"class":93,"line":94},[6196],{"type":34,"tag":91,"props":6197,"children":6198},{"style":4745},[6199],{"type":40,"value":4748},{"type":34,"tag":91,"props":6201,"children":6202},{"class":93,"line":103},[6203],{"type":34,"tag":91,"props":6204,"children":6205},{"style":2904},[6206],{"type":40,"value":6207},"  schemaname,\n",{"type":34,"tag":91,"props":6209,"children":6210},{"class":93,"line":112},[6211],{"type":34,"tag":91,"props":6212,"children":6213},{"style":2904},[6214],{"type":40,"value":6215},"  tablename,\n",{"type":34,"tag":91,"props":6217,"children":6218},{"class":93,"line":121},[6219],{"type":34,"tag":91,"props":6220,"children":6221},{"style":2904},[6222],{"type":40,"value":6223},"  indexname,\n",{"type":34,"tag":91,"props":6225,"children":6226},{"class":93,"line":131},[6227,6232,6236],{"type":34,"tag":91,"props":6228,"children":6229},{"style":2904},[6230],{"type":40,"value":6231},"  idx_scan ",{"type":34,"tag":91,"props":6233,"children":6234},{"style":4745},[6235],{"type":40,"value":4801},{"type":34,"tag":91,"props":6237,"children":6238},{"style":2904},[6239],{"type":40,"value":6240}," scans_since_restart\n",{"type":34,"tag":91,"props":6242,"children":6243},{"class":93,"line":140},[6244,6248],{"type":34,"tag":91,"props":6245,"children":6246},{"style":4745},[6247],{"type":40,"value":4889},{"type":34,"tag":91,"props":6249,"children":6250},{"style":2904},[6251],{"type":40,"value":6252}," pg_stat_user_indexes\n",{"type":34,"tag":91,"props":6254,"children":6255},{"class":93,"line":149},[6256,6260,6265,6269],{"type":34,"tag":91,"props":6257,"children":6258},{"style":4745},[6259],{"type":40,"value":5174},{"type":34,"tag":91,"props":6261,"children":6262},{"style":2904},[6263],{"type":40,"value":6264}," idx_scan ",{"type":34,"tag":91,"props":6266,"children":6267},{"style":4745},[6268],{"type":40,"value":5389},{"type":34,"tag":91,"props":6270,"children":6271},{"style":3305},[6272],{"type":40,"value":6273}," 0\n",{"type":34,"tag":91,"props":6275,"children":6276},{"class":93,"line":158},[6277,6281,6286,6291,6296],{"type":34,"tag":91,"props":6278,"children":6279},{"style":4745},[6280],{"type":40,"value":5941},{"type":34,"tag":91,"props":6282,"children":6283},{"style":2904},[6284],{"type":40,"value":6285}," indexrelname ",{"type":34,"tag":91,"props":6287,"children":6288},{"style":4745},[6289],{"type":40,"value":6290},"NOT",{"type":34,"tag":91,"props":6292,"children":6293},{"style":4745},[6294],{"type":40,"value":6295}," LIKE",{"type":34,"tag":91,"props":6297,"children":6298},{"style":2921},[6299],{"type":40,"value":6300}," '%_pkey'\n",{"type":34,"tag":91,"props":6302,"children":6303},{"class":93,"line":167},[6304,6308],{"type":34,"tag":91,"props":6305,"children":6306},{"style":4745},[6307],{"type":40,"value":4902},{"type":34,"tag":91,"props":6309,"children":6310},{"style":2904},[6311],{"type":40,"value":6312}," schemaname, tablename;\n",{"type":34,"tag":43,"props":6314,"children":6315},{},[6316],{"type":40,"value":6317},"Drop any index that shows zero scans and wasn't created in the last 24 hours.",{"type":34,"tag":35,"props":6319,"children":6321},{"id":6320},"caching-the-force-multiplier",[6322],{"type":40,"value":6323},"Caching: The Force Multiplier",{"type":34,"tag":43,"props":6325,"children":6326},{},[6327],{"type":40,"value":6328},"Once queries are fast, caching keeps frequently-read data out of the database entirely.",{"type":34,"tag":2626,"props":6330,"children":6332},{"id":6331},"application-level-caching-with-redis",[6333],{"type":40,"value":6334},"Application-Level Caching with Redis",{"type":34,"tag":81,"props":6336,"children":6340},{"className":6337,"code":6338,"language":6339,"meta":7,"style":7},"language-csharp shiki shiki-themes github-light","public async Task\u003CProduct> GetProductAsync(int id)\n{\n    var cacheKey = $\"product:{id}\";\n\n    var cached = await _cache.GetStringAsync(cacheKey);\n    if (cached is not null)\n        return JsonSerializer.Deserialize\u003CProduct>(cached)!;\n\n    var product = await _db.Products\n        .AsNoTracking()\n        .Include(p => p.Category)\n        .FirstOrDefaultAsync(p => p.Id == id);\n\n    if (product is not null)\n    {\n        await _cache.SetStringAsync(\n            cacheKey,\n            JsonSerializer.Serialize(product),\n            new DistributedCacheEntryOptions\n            {\n                AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)\n            });\n    }\n\n    return product!;\n}\n","csharp",[6341],{"type":34,"tag":49,"props":6342,"children":6343},{"__ignoreMap":7},[6344,6399,6407,6442,6449,6485,6517,6557,6564,6589,6607,6637,6676,6683,6711,6719,6741,6749,6767,6780,6788,6823,6831,6838,6845,6865],{"type":34,"tag":91,"props":6345,"children":6346},{"class":93,"line":94},[6347,6352,6357,6362,6367,6371,6376,6381,6385,6390,6395],{"type":34,"tag":91,"props":6348,"children":6349},{"style":4745},[6350],{"type":40,"value":6351},"public",{"type":34,"tag":91,"props":6353,"children":6354},{"style":4745},[6355],{"type":40,"value":6356}," async",{"type":34,"tag":91,"props":6358,"children":6359},{"style":6007},[6360],{"type":40,"value":6361}," Task",{"type":34,"tag":91,"props":6363,"children":6364},{"style":2904},[6365],{"type":40,"value":6366},"\u003C",{"type":34,"tag":91,"props":6368,"children":6369},{"style":6007},[6370],{"type":40,"value":366},{"type":34,"tag":91,"props":6372,"children":6373},{"style":2904},[6374],{"type":40,"value":6375},"> ",{"type":34,"tag":91,"props":6377,"children":6378},{"style":6007},[6379],{"type":40,"value":6380},"GetProductAsync",{"type":34,"tag":91,"props":6382,"children":6383},{"style":2904},[6384],{"type":40,"value":5037},{"type":34,"tag":91,"props":6386,"children":6387},{"style":4745},[6388],{"type":40,"value":6389},"int",{"type":34,"tag":91,"props":6391,"children":6392},{"style":6007},[6393],{"type":40,"value":6394}," id",{"type":34,"tag":91,"props":6396,"children":6397},{"style":2904},[6398],{"type":40,"value":477},{"type":34,"tag":91,"props":6400,"children":6401},{"class":93,"line":103},[6402],{"type":34,"tag":91,"props":6403,"children":6404},{"style":2904},[6405],{"type":40,"value":6406},"{\n",{"type":34,"tag":91,"props":6408,"children":6409},{"class":93,"line":112},[6410,6415,6420,6424,6429,6433,6438],{"type":34,"tag":91,"props":6411,"children":6412},{"style":4745},[6413],{"type":40,"value":6414},"    var",{"type":34,"tag":91,"props":6416,"children":6417},{"style":6007},[6418],{"type":40,"value":6419}," cacheKey",{"type":34,"tag":91,"props":6421,"children":6422},{"style":4745},[6423],{"type":40,"value":5152},{"type":34,"tag":91,"props":6425,"children":6426},{"style":2921},[6427],{"type":40,"value":6428}," $\"product:{",{"type":34,"tag":91,"props":6430,"children":6431},{"style":2904},[6432],{"type":40,"value":5568},{"type":34,"tag":91,"props":6434,"children":6435},{"style":2921},[6436],{"type":40,"value":6437},"}\"",{"type":34,"tag":91,"props":6439,"children":6440},{"style":2904},[6441],{"type":40,"value":4930},{"type":34,"tag":91,"props":6443,"children":6444},{"class":93,"line":121},[6445],{"type":34,"tag":91,"props":6446,"children":6447},{"emptyLinePlaceholder":125},[6448],{"type":40,"value":128},{"type":34,"tag":91,"props":6450,"children":6451},{"class":93,"line":131},[6452,6456,6461,6465,6470,6475,6480],{"type":34,"tag":91,"props":6453,"children":6454},{"style":4745},[6455],{"type":40,"value":6414},{"type":34,"tag":91,"props":6457,"children":6458},{"style":6007},[6459],{"type":40,"value":6460}," cached",{"type":34,"tag":91,"props":6462,"children":6463},{"style":4745},[6464],{"type":40,"value":5152},{"type":34,"tag":91,"props":6466,"children":6467},{"style":4745},[6468],{"type":40,"value":6469}," await",{"type":34,"tag":91,"props":6471,"children":6472},{"style":2904},[6473],{"type":40,"value":6474}," _cache.",{"type":34,"tag":91,"props":6476,"children":6477},{"style":6007},[6478],{"type":40,"value":6479},"GetStringAsync",{"type":34,"tag":91,"props":6481,"children":6482},{"style":2904},[6483],{"type":40,"value":6484},"(cacheKey);\n",{"type":34,"tag":91,"props":6486,"children":6487},{"class":93,"line":140},[6488,6493,6498,6503,6508,6513],{"type":34,"tag":91,"props":6489,"children":6490},{"style":4745},[6491],{"type":40,"value":6492},"    if",{"type":34,"tag":91,"props":6494,"children":6495},{"style":2904},[6496],{"type":40,"value":6497}," (cached ",{"type":34,"tag":91,"props":6499,"children":6500},{"style":4745},[6501],{"type":40,"value":6502},"is",{"type":34,"tag":91,"props":6504,"children":6505},{"style":4745},[6506],{"type":40,"value":6507}," not",{"type":34,"tag":91,"props":6509,"children":6510},{"style":3305},[6511],{"type":40,"value":6512}," null",{"type":34,"tag":91,"props":6514,"children":6515},{"style":2904},[6516],{"type":40,"value":477},{"type":34,"tag":91,"props":6518,"children":6519},{"class":93,"line":149},[6520,6525,6530,6535,6539,6543,6548,6553],{"type":34,"tag":91,"props":6521,"children":6522},{"style":4745},[6523],{"type":40,"value":6524},"        return",{"type":34,"tag":91,"props":6526,"children":6527},{"style":2904},[6528],{"type":40,"value":6529}," JsonSerializer.",{"type":34,"tag":91,"props":6531,"children":6532},{"style":6007},[6533],{"type":40,"value":6534},"Deserialize",{"type":34,"tag":91,"props":6536,"children":6537},{"style":2904},[6538],{"type":40,"value":6366},{"type":34,"tag":91,"props":6540,"children":6541},{"style":6007},[6542],{"type":40,"value":366},{"type":34,"tag":91,"props":6544,"children":6545},{"style":2904},[6546],{"type":40,"value":6547},">(cached)",{"type":34,"tag":91,"props":6549,"children":6550},{"style":4745},[6551],{"type":40,"value":6552},"!",{"type":34,"tag":91,"props":6554,"children":6555},{"style":2904},[6556],{"type":40,"value":4930},{"type":34,"tag":91,"props":6558,"children":6559},{"class":93,"line":158},[6560],{"type":34,"tag":91,"props":6561,"children":6562},{"emptyLinePlaceholder":125},[6563],{"type":40,"value":128},{"type":34,"tag":91,"props":6565,"children":6566},{"class":93,"line":167},[6567,6571,6576,6580,6584],{"type":34,"tag":91,"props":6568,"children":6569},{"style":4745},[6570],{"type":40,"value":6414},{"type":34,"tag":91,"props":6572,"children":6573},{"style":6007},[6574],{"type":40,"value":6575}," product",{"type":34,"tag":91,"props":6577,"children":6578},{"style":4745},[6579],{"type":40,"value":5152},{"type":34,"tag":91,"props":6581,"children":6582},{"style":4745},[6583],{"type":40,"value":6469},{"type":34,"tag":91,"props":6585,"children":6586},{"style":2904},[6587],{"type":40,"value":6588}," _db.Products\n",{"type":34,"tag":91,"props":6590,"children":6591},{"class":93,"line":176},[6592,6597,6602],{"type":34,"tag":91,"props":6593,"children":6594},{"style":2904},[6595],{"type":40,"value":6596},"        .",{"type":34,"tag":91,"props":6598,"children":6599},{"style":6007},[6600],{"type":40,"value":6601},"AsNoTracking",{"type":34,"tag":91,"props":6603,"children":6604},{"style":2904},[6605],{"type":40,"value":6606},"()\n",{"type":34,"tag":91,"props":6608,"children":6609},{"class":93,"line":184},[6610,6614,6619,6623,6627,6632],{"type":34,"tag":91,"props":6611,"children":6612},{"style":2904},[6613],{"type":40,"value":6596},{"type":34,"tag":91,"props":6615,"children":6616},{"style":6007},[6617],{"type":40,"value":6618},"Include",{"type":34,"tag":91,"props":6620,"children":6621},{"style":2904},[6622],{"type":40,"value":5037},{"type":34,"tag":91,"props":6624,"children":6625},{"style":6007},[6626],{"type":40,"value":43},{"type":34,"tag":91,"props":6628,"children":6629},{"style":4745},[6630],{"type":40,"value":6631}," =>",{"type":34,"tag":91,"props":6633,"children":6634},{"style":2904},[6635],{"type":40,"value":6636}," p.Category)\n",{"type":34,"tag":91,"props":6638,"children":6639},{"class":93,"line":193},[6640,6644,6649,6653,6657,6661,6666,6671],{"type":34,"tag":91,"props":6641,"children":6642},{"style":2904},[6643],{"type":40,"value":6596},{"type":34,"tag":91,"props":6645,"children":6646},{"style":6007},[6647],{"type":40,"value":6648},"FirstOrDefaultAsync",{"type":34,"tag":91,"props":6650,"children":6651},{"style":2904},[6652],{"type":40,"value":5037},{"type":34,"tag":91,"props":6654,"children":6655},{"style":6007},[6656],{"type":40,"value":43},{"type":34,"tag":91,"props":6658,"children":6659},{"style":4745},[6660],{"type":40,"value":6631},{"type":34,"tag":91,"props":6662,"children":6663},{"style":2904},[6664],{"type":40,"value":6665}," p.Id ",{"type":34,"tag":91,"props":6667,"children":6668},{"style":4745},[6669],{"type":40,"value":6670},"==",{"type":34,"tag":91,"props":6672,"children":6673},{"style":2904},[6674],{"type":40,"value":6675}," id);\n",{"type":34,"tag":91,"props":6677,"children":6678},{"class":93,"line":202},[6679],{"type":34,"tag":91,"props":6680,"children":6681},{"emptyLinePlaceholder":125},[6682],{"type":40,"value":128},{"type":34,"tag":91,"props":6684,"children":6685},{"class":93,"line":210},[6686,6690,6695,6699,6703,6707],{"type":34,"tag":91,"props":6687,"children":6688},{"style":4745},[6689],{"type":40,"value":6492},{"type":34,"tag":91,"props":6691,"children":6692},{"style":2904},[6693],{"type":40,"value":6694}," (product ",{"type":34,"tag":91,"props":6696,"children":6697},{"style":4745},[6698],{"type":40,"value":6502},{"type":34,"tag":91,"props":6700,"children":6701},{"style":4745},[6702],{"type":40,"value":6507},{"type":34,"tag":91,"props":6704,"children":6705},{"style":3305},[6706],{"type":40,"value":6512},{"type":34,"tag":91,"props":6708,"children":6709},{"style":2904},[6710],{"type":40,"value":477},{"type":34,"tag":91,"props":6712,"children":6713},{"class":93,"line":218},[6714],{"type":34,"tag":91,"props":6715,"children":6716},{"style":2904},[6717],{"type":40,"value":6718},"    {\n",{"type":34,"tag":91,"props":6720,"children":6721},{"class":93,"line":227},[6722,6727,6731,6736],{"type":34,"tag":91,"props":6723,"children":6724},{"style":4745},[6725],{"type":40,"value":6726},"        await",{"type":34,"tag":91,"props":6728,"children":6729},{"style":2904},[6730],{"type":40,"value":6474},{"type":34,"tag":91,"props":6732,"children":6733},{"style":6007},[6734],{"type":40,"value":6735},"SetStringAsync",{"type":34,"tag":91,"props":6737,"children":6738},{"style":2904},[6739],{"type":40,"value":6740},"(\n",{"type":34,"tag":91,"props":6742,"children":6743},{"class":93,"line":236},[6744],{"type":34,"tag":91,"props":6745,"children":6746},{"style":2904},[6747],{"type":40,"value":6748},"            cacheKey,\n",{"type":34,"tag":91,"props":6750,"children":6751},{"class":93,"line":245},[6752,6757,6762],{"type":34,"tag":91,"props":6753,"children":6754},{"style":2904},[6755],{"type":40,"value":6756},"            JsonSerializer.",{"type":34,"tag":91,"props":6758,"children":6759},{"style":6007},[6760],{"type":40,"value":6761},"Serialize",{"type":34,"tag":91,"props":6763,"children":6764},{"style":2904},[6765],{"type":40,"value":6766},"(product),\n",{"type":34,"tag":91,"props":6768,"children":6769},{"class":93,"line":254},[6770,6775],{"type":34,"tag":91,"props":6771,"children":6772},{"style":4745},[6773],{"type":40,"value":6774},"            new",{"type":34,"tag":91,"props":6776,"children":6777},{"style":6007},[6778],{"type":40,"value":6779}," DistributedCacheEntryOptions\n",{"type":34,"tag":91,"props":6781,"children":6782},{"class":93,"line":262},[6783],{"type":34,"tag":91,"props":6784,"children":6785},{"style":2904},[6786],{"type":40,"value":6787},"            {\n",{"type":34,"tag":91,"props":6789,"children":6790},{"class":93,"line":270},[6791,6796,6800,6805,6810,6814,6819],{"type":34,"tag":91,"props":6792,"children":6793},{"style":2904},[6794],{"type":40,"value":6795},"                AbsoluteExpirationRelativeToNow ",{"type":34,"tag":91,"props":6797,"children":6798},{"style":4745},[6799],{"type":40,"value":5389},{"type":34,"tag":91,"props":6801,"children":6802},{"style":2904},[6803],{"type":40,"value":6804}," TimeSpan.",{"type":34,"tag":91,"props":6806,"children":6807},{"style":6007},[6808],{"type":40,"value":6809},"FromMinutes",{"type":34,"tag":91,"props":6811,"children":6812},{"style":2904},[6813],{"type":40,"value":5037},{"type":34,"tag":91,"props":6815,"children":6816},{"style":3305},[6817],{"type":40,"value":6818},"15",{"type":34,"tag":91,"props":6820,"children":6821},{"style":2904},[6822],{"type":40,"value":477},{"type":34,"tag":91,"props":6824,"children":6825},{"class":93,"line":279},[6826],{"type":34,"tag":91,"props":6827,"children":6828},{"style":2904},[6829],{"type":40,"value":6830},"            });\n",{"type":34,"tag":91,"props":6832,"children":6833},{"class":93,"line":288},[6834],{"type":34,"tag":91,"props":6835,"children":6836},{"style":2904},[6837],{"type":40,"value":578},{"type":34,"tag":91,"props":6839,"children":6840},{"class":93,"line":297},[6841],{"type":34,"tag":91,"props":6842,"children":6843},{"emptyLinePlaceholder":125},[6844],{"type":40,"value":128},{"type":34,"tag":91,"props":6846,"children":6847},{"class":93,"line":306},[6848,6853,6857,6861],{"type":34,"tag":91,"props":6849,"children":6850},{"style":4745},[6851],{"type":40,"value":6852},"    return",{"type":34,"tag":91,"props":6854,"children":6855},{"style":2904},[6856],{"type":40,"value":6575},{"type":34,"tag":91,"props":6858,"children":6859},{"style":4745},[6860],{"type":40,"value":6552},{"type":34,"tag":91,"props":6862,"children":6863},{"style":2904},[6864],{"type":40,"value":4930},{"type":34,"tag":91,"props":6866,"children":6867},{"class":93,"line":315},[6868],{"type":34,"tag":91,"props":6869,"children":6870},{"style":2904},[6871],{"type":40,"value":173},{"type":34,"tag":43,"props":6873,"children":6874},{},[6875],{"type":40,"value":6876},"Cache TTL is the hardest decision. Our rule of thumb: start at half the expected staleness tolerance, then tune based on cache-hit ratio monitoring.",{"type":34,"tag":2626,"props":6878,"children":6880},{"id":6879},"materialised-views-for-analytics",[6881],{"type":40,"value":6882},"Materialised Views for Analytics",{"type":34,"tag":43,"props":6884,"children":6885},{},[6886],{"type":40,"value":6887},"Complex analytical queries over large tables should never run live against OLTP data. Materialise the result:",{"type":34,"tag":81,"props":6889,"children":6891},{"className":4725,"code":6890,"language":4727,"meta":7,"style":7},"CREATE MATERIALIZED VIEW mv_monthly_revenue AS\nSELECT\n    DATE_TRUNC('month', order_date)  AS month,\n    product_category,\n    SUM(amount)                       AS revenue,\n    COUNT(*)                          AS orders\nFROM orders o\nJOIN products p ON o.product_id = p.id\nGROUP BY 1, 2;\n\nCREATE INDEX ON mv_monthly_revenue (month);\n\n-- Refresh nightly (or on-demand after large data loads)\nREFRESH MATERIALIZED VIEW CONCURRENTLY mv_monthly_revenue;\n",[6892],{"type":34,"tag":49,"props":6893,"children":6894},{"__ignoreMap":7},[6895,6912,6919,6950,6958,6979,7008,7020,7068,7092,7099,7129,7136,7144],{"type":34,"tag":91,"props":6896,"children":6897},{"class":93,"line":94},[6898,6902,6907],{"type":34,"tag":91,"props":6899,"children":6900},{"style":4745},[6901],{"type":40,"value":5999},{"type":34,"tag":91,"props":6903,"children":6904},{"style":2904},[6905],{"type":40,"value":6906}," MATERIALIZED VIEW mv_monthly_revenue ",{"type":34,"tag":91,"props":6908,"children":6909},{"style":4745},[6910],{"type":40,"value":6911},"AS\n",{"type":34,"tag":91,"props":6913,"children":6914},{"class":93,"line":103},[6915],{"type":34,"tag":91,"props":6916,"children":6917},{"style":4745},[6918],{"type":40,"value":4748},{"type":34,"tag":91,"props":6920,"children":6921},{"class":93,"line":112},[6922,6927,6932,6937,6941,6946],{"type":34,"tag":91,"props":6923,"children":6924},{"style":2904},[6925],{"type":40,"value":6926},"    DATE_TRUNC(",{"type":34,"tag":91,"props":6928,"children":6929},{"style":2921},[6930],{"type":40,"value":6931},"'month'",{"type":34,"tag":91,"props":6933,"children":6934},{"style":2904},[6935],{"type":40,"value":6936},", order_date)  ",{"type":34,"tag":91,"props":6938,"children":6939},{"style":4745},[6940],{"type":40,"value":4801},{"type":34,"tag":91,"props":6942,"children":6943},{"style":4745},[6944],{"type":40,"value":6945}," month",{"type":34,"tag":91,"props":6947,"children":6948},{"style":2904},[6949],{"type":40,"value":5005},{"type":34,"tag":91,"props":6951,"children":6952},{"class":93,"line":121},[6953],{"type":34,"tag":91,"props":6954,"children":6955},{"style":2904},[6956],{"type":40,"value":6957},"    product_category,\n",{"type":34,"tag":91,"props":6959,"children":6960},{"class":93,"line":131},[6961,6965,6970,6974],{"type":34,"tag":91,"props":6962,"children":6963},{"style":3305},[6964],{"type":40,"value":5073},{"type":34,"tag":91,"props":6966,"children":6967},{"style":2904},[6968],{"type":40,"value":6969},"(amount)                       ",{"type":34,"tag":91,"props":6971,"children":6972},{"style":4745},[6973],{"type":40,"value":4801},{"type":34,"tag":91,"props":6975,"children":6976},{"style":2904},[6977],{"type":40,"value":6978}," revenue,\n",{"type":34,"tag":91,"props":6980,"children":6981},{"class":93,"line":140},[6982,6986,6990,6995,7000,7004],{"type":34,"tag":91,"props":6983,"children":6984},{"style":3305},[6985],{"type":40,"value":5032},{"type":34,"tag":91,"props":6987,"children":6988},{"style":2904},[6989],{"type":40,"value":5037},{"type":34,"tag":91,"props":6991,"children":6992},{"style":4745},[6993],{"type":40,"value":6994},"*",{"type":34,"tag":91,"props":6996,"children":6997},{"style":2904},[6998],{"type":40,"value":6999},")                          ",{"type":34,"tag":91,"props":7001,"children":7002},{"style":4745},[7003],{"type":40,"value":4801},{"type":34,"tag":91,"props":7005,"children":7006},{"style":2904},[7007],{"type":40,"value":5710},{"type":34,"tag":91,"props":7009,"children":7010},{"class":93,"line":149},[7011,7015],{"type":34,"tag":91,"props":7012,"children":7013},{"style":4745},[7014],{"type":40,"value":4889},{"type":34,"tag":91,"props":7016,"children":7017},{"style":2904},[7018],{"type":40,"value":7019}," orders o\n",{"type":34,"tag":91,"props":7021,"children":7022},{"class":93,"line":158},[7023,7028,7033,7037,7041,7045,7050,7054,7059,7063],{"type":34,"tag":91,"props":7024,"children":7025},{"style":4745},[7026],{"type":40,"value":7027},"JOIN",{"type":34,"tag":91,"props":7029,"children":7030},{"style":2904},[7031],{"type":40,"value":7032}," products p ",{"type":34,"tag":91,"props":7034,"children":7035},{"style":4745},[7036],{"type":40,"value":5134},{"type":34,"tag":91,"props":7038,"children":7039},{"style":3305},[7040],{"type":40,"value":5157},{"type":34,"tag":91,"props":7042,"children":7043},{"style":2904},[7044],{"type":40,"value":2549},{"type":34,"tag":91,"props":7046,"children":7047},{"style":3305},[7048],{"type":40,"value":7049},"product_id",{"type":34,"tag":91,"props":7051,"children":7052},{"style":4745},[7053],{"type":40,"value":5152},{"type":34,"tag":91,"props":7055,"children":7056},{"style":3305},[7057],{"type":40,"value":7058}," p",{"type":34,"tag":91,"props":7060,"children":7061},{"style":2904},[7062],{"type":40,"value":2549},{"type":34,"tag":91,"props":7064,"children":7065},{"style":3305},[7066],{"type":40,"value":7067},"id\n",{"type":34,"tag":91,"props":7069,"children":7070},{"class":93,"line":167},[7071,7075,7080,7084,7088],{"type":34,"tag":91,"props":7072,"children":7073},{"style":4745},[7074],{"type":40,"value":5205},{"type":34,"tag":91,"props":7076,"children":7077},{"style":3305},[7078],{"type":40,"value":7079}," 1",{"type":34,"tag":91,"props":7081,"children":7082},{"style":2904},[7083],{"type":40,"value":3229},{"type":34,"tag":91,"props":7085,"children":7086},{"style":3305},[7087],{"type":40,"value":4791},{"type":34,"tag":91,"props":7089,"children":7090},{"style":2904},[7091],{"type":40,"value":4930},{"type":34,"tag":91,"props":7093,"children":7094},{"class":93,"line":176},[7095],{"type":34,"tag":91,"props":7096,"children":7097},{"emptyLinePlaceholder":125},[7098],{"type":40,"value":128},{"type":34,"tag":91,"props":7100,"children":7101},{"class":93,"line":184},[7102,7106,7110,7115,7120,7125],{"type":34,"tag":91,"props":7103,"children":7104},{"style":4745},[7105],{"type":40,"value":5999},{"type":34,"tag":91,"props":7107,"children":7108},{"style":4745},[7109],{"type":40,"value":6004},{"type":34,"tag":91,"props":7111,"children":7112},{"style":6007},[7113],{"type":40,"value":7114}," ON",{"type":34,"tag":91,"props":7116,"children":7117},{"style":2904},[7118],{"type":40,"value":7119}," mv_monthly_revenue (",{"type":34,"tag":91,"props":7121,"children":7122},{"style":4745},[7123],{"type":40,"value":7124},"month",{"type":34,"tag":91,"props":7126,"children":7127},{"style":2904},[7128],{"type":40,"value":6169},{"type":34,"tag":91,"props":7130,"children":7131},{"class":93,"line":193},[7132],{"type":34,"tag":91,"props":7133,"children":7134},{"emptyLinePlaceholder":125},[7135],{"type":40,"value":128},{"type":34,"tag":91,"props":7137,"children":7138},{"class":93,"line":202},[7139],{"type":34,"tag":91,"props":7140,"children":7141},{"style":2895},[7142],{"type":40,"value":7143},"-- Refresh nightly (or on-demand after large data loads)\n",{"type":34,"tag":91,"props":7145,"children":7146},{"class":93,"line":210},[7147],{"type":34,"tag":91,"props":7148,"children":7149},{"style":2904},[7150],{"type":40,"value":7151},"REFRESH MATERIALIZED VIEW CONCURRENTLY mv_monthly_revenue;\n",{"type":34,"tag":43,"props":7153,"children":7154},{},[7155,7161],{"type":34,"tag":49,"props":7156,"children":7158},{"className":7157},[],[7159],{"type":40,"value":7160},"CONCURRENTLY",{"type":40,"value":7162}," lets reads continue during the refresh — zero downtime.",{"type":34,"tag":35,"props":7164,"children":7166},{"id":7165},"real-world-results-e-commerce-platform-optimisation",[7167],{"type":40,"value":7168},"Real-World Results: E-Commerce Platform Optimisation",{"type":34,"tag":43,"props":7170,"children":7171},{},[7172],{"type":40,"value":7173},"An e-commerce client came to us handling 50,000+ daily orders with page timeouts during flash sales. Our four-week audit and remediation:",{"type":34,"tag":1968,"props":7175,"children":7176},{},[7177,7193],{"type":34,"tag":1972,"props":7178,"children":7179},{},[7180],{"type":34,"tag":1976,"props":7181,"children":7182},{},[7183,7188],{"type":34,"tag":1980,"props":7184,"children":7185},{},[7186],{"type":40,"value":7187},"Action",{"type":34,"tag":1980,"props":7189,"children":7190},{},[7191],{"type":40,"value":7192},"Impact",{"type":34,"tag":1996,"props":7194,"children":7195},{},[7196,7209,7222,7235,7248],{"type":34,"tag":1976,"props":7197,"children":7198},{},[7199,7204],{"type":34,"tag":2003,"props":7200,"children":7201},{},[7202],{"type":40,"value":7203},"Rewrote 15 highest-cost queries",{"type":34,"tag":2003,"props":7205,"children":7206},{},[7207],{"type":40,"value":7208},"−60% DB CPU usage",{"type":34,"tag":1976,"props":7210,"children":7211},{},[7212,7217],{"type":34,"tag":2003,"props":7213,"children":7214},{},[7215],{"type":40,"value":7216},"Added 8 strategic covering indexes",{"type":34,"tag":2003,"props":7218,"children":7219},{},[7220],{"type":40,"value":7221},"Avg query time: 1200ms → 85ms",{"type":34,"tag":1976,"props":7223,"children":7224},{},[7225,7230],{"type":34,"tag":2003,"props":7226,"children":7227},{},[7228],{"type":40,"value":7229},"Removed 5 unused indexes",{"type":34,"tag":2003,"props":7231,"children":7232},{},[7233],{"type":40,"value":7234},"Write throughput +18%",{"type":34,"tag":1976,"props":7236,"children":7237},{},[7238,7243],{"type":34,"tag":2003,"props":7239,"children":7240},{},[7241],{"type":40,"value":7242},"Added Redis for product catalogue",{"type":34,"tag":2003,"props":7244,"children":7245},{},[7246],{"type":40,"value":7247},"Cache hit rate 94%",{"type":34,"tag":1976,"props":7249,"children":7250},{},[7251,7264],{"type":34,"tag":2003,"props":7252,"children":7253},{},[7254,7256,7262],{"type":40,"value":7255},"Partitioned ",{"type":34,"tag":49,"props":7257,"children":7259},{"className":7258},[],[7260],{"type":40,"value":7261},"orders",{"type":40,"value":7263}," table by month",{"type":34,"tag":2003,"props":7265,"children":7266},{},[7267],{"type":40,"value":7268},"Flash sale timeouts eliminated",{"type":34,"tag":43,"props":7270,"children":7271},{},[7272],{"type":40,"value":7273},"The business outcome: a 24% increase in conversion rate—driven entirely by improved responsiveness. No new hardware was purchased.",{"type":34,"tag":35,"props":7275,"children":7277},{"id":7276},"schema-design-getting-it-right-upstream",[7278],{"type":40,"value":7279},"Schema Design: Getting It Right Upstream",{"type":34,"tag":43,"props":7281,"children":7282},{},[7283],{"type":40,"value":7284},"Optimising a poorly designed schema is fighting uphill. Principles that pay off long-term:",{"type":34,"tag":1762,"props":7286,"children":7287},{},[7288,7298,7308,7332],{"type":34,"tag":1766,"props":7289,"children":7290},{},[7291,7296],{"type":34,"tag":1770,"props":7292,"children":7293},{},[7294],{"type":40,"value":7295},"Normalise transactional tables",{"type":40,"value":7297}," — eliminating update anomalies is worth the occasional join",{"type":34,"tag":1766,"props":7299,"children":7300},{},[7301,7306],{"type":34,"tag":1770,"props":7302,"children":7303},{},[7304],{"type":40,"value":7305},"Denormalise for reporting",{"type":40,"value":7307}," — create dedicated summary tables or materialised views rather than forcing complex joins into every report query",{"type":34,"tag":1766,"props":7309,"children":7310},{},[7311,7316,7318,7323,7324,7330],{"type":34,"tag":1770,"props":7312,"children":7313},{},[7314],{"type":40,"value":7315},"Partition large tables",{"type":40,"value":7317}," — partition ",{"type":34,"tag":49,"props":7319,"children":7321},{"className":7320},[],[7322],{"type":40,"value":7261},{"type":40,"value":4424},{"type":34,"tag":49,"props":7325,"children":7327},{"className":7326},[],[7328],{"type":40,"value":7329},"events",{"type":40,"value":7331}," tables by date range so old data never slows current queries",{"type":34,"tag":1766,"props":7333,"children":7334},{},[7335,7340,7341,7347,7349,7355,7357,7363,7365,7371],{"type":34,"tag":1770,"props":7336,"children":7337},{},[7338],{"type":40,"value":7339},"Use appropriate data types",{"type":40,"value":2854},{"type":34,"tag":49,"props":7342,"children":7344},{"className":7343},[],[7345],{"type":40,"value":7346},"BIGINT",{"type":40,"value":7348}," for IDs that will exceed 2 billion, ",{"type":34,"tag":49,"props":7350,"children":7352},{"className":7351},[],[7353],{"type":40,"value":7354},"TIMESTAMPTZ",{"type":40,"value":7356}," for timestamps (always store UTC), ",{"type":34,"tag":49,"props":7358,"children":7360},{"className":7359},[],[7361],{"type":40,"value":7362},"NUMERIC(10,2)",{"type":40,"value":7364}," for money (never ",{"type":34,"tag":49,"props":7366,"children":7368},{"className":7367},[],[7369],{"type":40,"value":7370},"FLOAT",{"type":40,"value":5859},{"type":34,"tag":43,"props":7373,"children":7374},{},[7375],{"type":40,"value":7376},"Database performance is a product of schema design, query patterns, and infrastructure working together. Fix all three, and you'll handle 10× the traffic on the same hardware.",{"type":34,"tag":1823,"props":7378,"children":7379},{},[7380],{"type":40,"value":1827},{"title":7,"searchDepth":112,"depth":112,"links":7382},[7383,7384,7385,7390,7396,7400,7401],{"id":4644,"depth":103,"text":4647},{"id":4660,"depth":103,"text":4663},{"id":4938,"depth":103,"text":4941,"children":7386},[7387,7388,7389],{"id":4944,"depth":112,"text":4947},{"id":5329,"depth":112,"text":5332},{"id":5472,"depth":112,"text":5475},{"id":5770,"depth":103,"text":5773,"children":7391},[7392,7393,7394,7395],{"id":5781,"depth":112,"text":5784},{"id":5867,"depth":112,"text":5870},{"id":6077,"depth":112,"text":6080},{"id":6177,"depth":112,"text":6180},{"id":6320,"depth":103,"text":6323,"children":7397},[7398,7399],{"id":6331,"depth":112,"text":6334},{"id":6879,"depth":112,"text":6882},{"id":7165,"depth":103,"text":7168},{"id":7276,"depth":103,"text":7279},"content:blog:database-optimization.md","blog/database-optimization.md","blog/database-optimization",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"slug":10,"date":11,"readTime":12,"category":13,"image":14,"imageCaption":15,"author":7406,"tags":7408,"body":7409,"_type":1837,"_id":1838,"_source":1839,"_file":1840,"_stem":1841,"_extension":1842},{"name":17,"role":18,"avatar":19,"bio":20,"social":7407},{"github":22,"twitter":23,"linkedin":24},[26,27,28,29,13],{"type":31,"children":7410,"toc":8921},[7411,7415,7425,7429,7433,7443,7652,7668,7672,8238,8248,8252,8256,8514,8518,8522,8654,8664,8668,8672,8846,8856,8860,8870,8905,8909,8913,8917],{"type":34,"tag":35,"props":7412,"children":7413},{"id":37},[7414],{"type":40,"value":41},{"type":34,"tag":43,"props":7416,"children":7417},{},[7418,7419,7424],{"type":40,"value":47},{"type":34,"tag":49,"props":7420,"children":7422},{"className":7421},[],[7423],{"type":40,"value":54},{"type":40,"value":56},{"type":34,"tag":43,"props":7426,"children":7427},{},[7428],{"type":40,"value":61},{"type":34,"tag":35,"props":7430,"children":7431},{"id":64},[7432],{"type":40,"value":67},{"type":34,"tag":43,"props":7434,"children":7435},{},[7436,7437,7442],{"type":40,"value":72},{"type":34,"tag":49,"props":7438,"children":7440},{"className":7439},[],[7441],{"type":40,"value":54},{"type":40,"value":79},{"type":34,"tag":81,"props":7444,"children":7445},{"className":83,"code":84,"language":85,"meta":7,"style":7},[7446],{"type":34,"tag":49,"props":7447,"children":7448},{"__ignoreMap":7},[7449,7456,7463,7470,7477,7484,7491,7498,7505,7512,7519,7526,7533,7540,7547,7554,7561,7568,7575,7582,7589,7596,7603,7610,7617,7624,7631,7638,7645],{"type":34,"tag":91,"props":7450,"children":7451},{"class":93,"line":94},[7452],{"type":34,"tag":91,"props":7453,"children":7454},{},[7455],{"type":40,"value":100},{"type":34,"tag":91,"props":7457,"children":7458},{"class":93,"line":103},[7459],{"type":34,"tag":91,"props":7460,"children":7461},{},[7462],{"type":40,"value":109},{"type":34,"tag":91,"props":7464,"children":7465},{"class":93,"line":112},[7466],{"type":34,"tag":91,"props":7467,"children":7468},{},[7469],{"type":40,"value":118},{"type":34,"tag":91,"props":7471,"children":7472},{"class":93,"line":121},[7473],{"type":34,"tag":91,"props":7474,"children":7475},{"emptyLinePlaceholder":125},[7476],{"type":40,"value":128},{"type":34,"tag":91,"props":7478,"children":7479},{"class":93,"line":131},[7480],{"type":34,"tag":91,"props":7481,"children":7482},{},[7483],{"type":40,"value":137},{"type":34,"tag":91,"props":7485,"children":7486},{"class":93,"line":140},[7487],{"type":34,"tag":91,"props":7488,"children":7489},{},[7490],{"type":40,"value":146},{"type":34,"tag":91,"props":7492,"children":7493},{"class":93,"line":149},[7494],{"type":34,"tag":91,"props":7495,"children":7496},{},[7497],{"type":40,"value":155},{"type":34,"tag":91,"props":7499,"children":7500},{"class":93,"line":158},[7501],{"type":34,"tag":91,"props":7502,"children":7503},{},[7504],{"type":40,"value":164},{"type":34,"tag":91,"props":7506,"children":7507},{"class":93,"line":167},[7508],{"type":34,"tag":91,"props":7509,"children":7510},{},[7511],{"type":40,"value":173},{"type":34,"tag":91,"props":7513,"children":7514},{"class":93,"line":176},[7515],{"type":34,"tag":91,"props":7516,"children":7517},{"emptyLinePlaceholder":125},[7518],{"type":40,"value":128},{"type":34,"tag":91,"props":7520,"children":7521},{"class":93,"line":184},[7522],{"type":34,"tag":91,"props":7523,"children":7524},{},[7525],{"type":40,"value":190},{"type":34,"tag":91,"props":7527,"children":7528},{"class":93,"line":193},[7529],{"type":34,"tag":91,"props":7530,"children":7531},{},[7532],{"type":40,"value":199},{"type":34,"tag":91,"props":7534,"children":7535},{"class":93,"line":202},[7536],{"type":34,"tag":91,"props":7537,"children":7538},{},[7539],{"type":40,"value":173},{"type":34,"tag":91,"props":7541,"children":7542},{"class":93,"line":210},[7543],{"type":34,"tag":91,"props":7544,"children":7545},{"emptyLinePlaceholder":125},[7546],{"type":40,"value":128},{"type":34,"tag":91,"props":7548,"children":7549},{"class":93,"line":218},[7550],{"type":34,"tag":91,"props":7551,"children":7552},{},[7553],{"type":40,"value":224},{"type":34,"tag":91,"props":7555,"children":7556},{"class":93,"line":227},[7557],{"type":34,"tag":91,"props":7558,"children":7559},{},[7560],{"type":40,"value":233},{"type":34,"tag":91,"props":7562,"children":7563},{"class":93,"line":236},[7564],{"type":34,"tag":91,"props":7565,"children":7566},{},[7567],{"type":40,"value":242},{"type":34,"tag":91,"props":7569,"children":7570},{"class":93,"line":245},[7571],{"type":34,"tag":91,"props":7572,"children":7573},{},[7574],{"type":40,"value":251},{"type":34,"tag":91,"props":7576,"children":7577},{"class":93,"line":254},[7578],{"type":34,"tag":91,"props":7579,"children":7580},{},[7581],{"type":40,"value":173},{"type":34,"tag":91,"props":7583,"children":7584},{"class":93,"line":262},[7585],{"type":34,"tag":91,"props":7586,"children":7587},{"emptyLinePlaceholder":125},[7588],{"type":40,"value":128},{"type":34,"tag":91,"props":7590,"children":7591},{"class":93,"line":270},[7592],{"type":34,"tag":91,"props":7593,"children":7594},{},[7595],{"type":40,"value":276},{"type":34,"tag":91,"props":7597,"children":7598},{"class":93,"line":279},[7599],{"type":34,"tag":91,"props":7600,"children":7601},{},[7602],{"type":40,"value":285},{"type":34,"tag":91,"props":7604,"children":7605},{"class":93,"line":288},[7606],{"type":34,"tag":91,"props":7607,"children":7608},{},[7609],{"type":40,"value":294},{"type":34,"tag":91,"props":7611,"children":7612},{"class":93,"line":297},[7613],{"type":34,"tag":91,"props":7614,"children":7615},{},[7616],{"type":40,"value":303},{"type":34,"tag":91,"props":7618,"children":7619},{"class":93,"line":306},[7620],{"type":34,"tag":91,"props":7621,"children":7622},{},[7623],{"type":40,"value":312},{"type":34,"tag":91,"props":7625,"children":7626},{"class":93,"line":315},[7627],{"type":34,"tag":91,"props":7628,"children":7629},{},[7630],{"type":40,"value":321},{"type":34,"tag":91,"props":7632,"children":7633},{"class":93,"line":324},[7634],{"type":34,"tag":91,"props":7635,"children":7636},{},[7637],{"type":40,"value":330},{"type":34,"tag":91,"props":7639,"children":7640},{"class":93,"line":333},[7641],{"type":34,"tag":91,"props":7642,"children":7643},{},[7644],{"type":40,"value":339},{"type":34,"tag":91,"props":7646,"children":7647},{"class":93,"line":342},[7648],{"type":34,"tag":91,"props":7649,"children":7650},{},[7651],{"type":40,"value":173},{"type":34,"tag":43,"props":7653,"children":7654},{},[7655,7656,7661,7662,7667],{"type":40,"value":352},{"type":34,"tag":49,"props":7657,"children":7659},{"className":7658},[],[7660],{"type":40,"value":358},{"type":40,"value":360},{"type":34,"tag":49,"props":7663,"children":7665},{"className":7664},[],[7666],{"type":40,"value":366},{"type":40,"value":368},{"type":34,"tag":35,"props":7669,"children":7670},{"id":371},[7671],{"type":40,"value":374},{"type":34,"tag":81,"props":7673,"children":7674},{"className":377,"code":378,"language":379,"meta":7,"style":7},[7675],{"type":34,"tag":49,"props":7676,"children":7677},{"__ignoreMap":7},[7678,7685,7692,7699,7706,7713,7720,7727,7734,7741,7748,7755,7762,7769,7776,7783,7790,7797,7804,7811,7818,7825,7832,7839,7846,7853,7860,7867,7874,7881,7888,7895,7902,7909,7916,7923,7930,7937,7944,7951,7958,7965,7972,7979,7986,7993,8000,8007,8014,8021,8028,8035,8042,8049,8056,8063,8070,8077,8084,8091,8098,8105,8112,8119,8126,8133,8140,8147,8154,8161,8168,8175,8182,8189,8196,8203,8210,8217,8224,8231],{"type":34,"tag":91,"props":7679,"children":7680},{"class":93,"line":94},[7681],{"type":34,"tag":91,"props":7682,"children":7683},{},[7684],{"type":40,"value":391},{"type":34,"tag":91,"props":7686,"children":7687},{"class":93,"line":103},[7688],{"type":34,"tag":91,"props":7689,"children":7690},{"emptyLinePlaceholder":125},[7691],{"type":40,"value":128},{"type":34,"tag":91,"props":7693,"children":7694},{"class":93,"line":112},[7695],{"type":34,"tag":91,"props":7696,"children":7697},{},[7698],{"type":40,"value":406},{"type":34,"tag":91,"props":7700,"children":7701},{"class":93,"line":121},[7702],{"type":34,"tag":91,"props":7703,"children":7704},{},[7705],{"type":40,"value":414},{"type":34,"tag":91,"props":7707,"children":7708},{"class":93,"line":131},[7709],{"type":34,"tag":91,"props":7710,"children":7711},{},[7712],{"type":40,"value":422},{"type":34,"tag":91,"props":7714,"children":7715},{"class":93,"line":140},[7716],{"type":34,"tag":91,"props":7717,"children":7718},{},[7719],{"type":40,"value":430},{"type":34,"tag":91,"props":7721,"children":7722},{"class":93,"line":149},[7723],{"type":34,"tag":91,"props":7724,"children":7725},{"emptyLinePlaceholder":125},[7726],{"type":40,"value":128},{"type":34,"tag":91,"props":7728,"children":7729},{"class":93,"line":158},[7730],{"type":34,"tag":91,"props":7731,"children":7732},{},[7733],{"type":40,"value":445},{"type":34,"tag":91,"props":7735,"children":7736},{"class":93,"line":167},[7737],{"type":34,"tag":91,"props":7738,"children":7739},{},[7740],{"type":40,"value":453},{"type":34,"tag":91,"props":7742,"children":7743},{"class":93,"line":176},[7744],{"type":34,"tag":91,"props":7745,"children":7746},{},[7747],{"type":40,"value":461},{"type":34,"tag":91,"props":7749,"children":7750},{"class":93,"line":184},[7751],{"type":34,"tag":91,"props":7752,"children":7753},{},[7754],{"type":40,"value":469},{"type":34,"tag":91,"props":7756,"children":7757},{"class":93,"line":193},[7758],{"type":34,"tag":91,"props":7759,"children":7760},{},[7761],{"type":40,"value":477},{"type":34,"tag":91,"props":7763,"children":7764},{"class":93,"line":202},[7765],{"type":34,"tag":91,"props":7766,"children":7767},{"emptyLinePlaceholder":125},[7768],{"type":40,"value":128},{"type":34,"tag":91,"props":7770,"children":7771},{"class":93,"line":210},[7772],{"type":34,"tag":91,"props":7773,"children":7774},{},[7775],{"type":40,"value":492},{"type":34,"tag":91,"props":7777,"children":7778},{"class":93,"line":218},[7779],{"type":34,"tag":91,"props":7780,"children":7781},{},[7782],{"type":40,"value":500},{"type":34,"tag":91,"props":7784,"children":7785},{"class":93,"line":227},[7786],{"type":34,"tag":91,"props":7787,"children":7788},{},[7789],{"type":40,"value":508},{"type":34,"tag":91,"props":7791,"children":7792},{"class":93,"line":236},[7793],{"type":34,"tag":91,"props":7794,"children":7795},{},[7796],{"type":40,"value":173},{"type":34,"tag":91,"props":7798,"children":7799},{"class":93,"line":245},[7800],{"type":34,"tag":91,"props":7801,"children":7802},{"emptyLinePlaceholder":125},[7803],{"type":40,"value":128},{"type":34,"tag":91,"props":7805,"children":7806},{"class":93,"line":254},[7807],{"type":34,"tag":91,"props":7808,"children":7809},{},[7810],{"type":40,"value":530},{"type":34,"tag":91,"props":7812,"children":7813},{"class":93,"line":262},[7814],{"type":34,"tag":91,"props":7815,"children":7816},{},[7817],{"type":40,"value":538},{"type":34,"tag":91,"props":7819,"children":7820},{"class":93,"line":270},[7821],{"type":34,"tag":91,"props":7822,"children":7823},{},[7824],{"type":40,"value":546},{"type":34,"tag":91,"props":7826,"children":7827},{"class":93,"line":279},[7828],{"type":34,"tag":91,"props":7829,"children":7830},{},[7831],{"type":40,"value":554},{"type":34,"tag":91,"props":7833,"children":7834},{"class":93,"line":288},[7835],{"type":34,"tag":91,"props":7836,"children":7837},{},[7838],{"type":40,"value":562},{"type":34,"tag":91,"props":7840,"children":7841},{"class":93,"line":297},[7842],{"type":34,"tag":91,"props":7843,"children":7844},{},[7845],{"type":40,"value":570},{"type":34,"tag":91,"props":7847,"children":7848},{"class":93,"line":306},[7849],{"type":34,"tag":91,"props":7850,"children":7851},{},[7852],{"type":40,"value":578},{"type":34,"tag":91,"props":7854,"children":7855},{"class":93,"line":315},[7856],{"type":34,"tag":91,"props":7857,"children":7858},{"emptyLinePlaceholder":125},[7859],{"type":40,"value":128},{"type":34,"tag":91,"props":7861,"children":7862},{"class":93,"line":324},[7863],{"type":34,"tag":91,"props":7864,"children":7865},{},[7866],{"type":40,"value":593},{"type":34,"tag":91,"props":7868,"children":7869},{"class":93,"line":333},[7870],{"type":34,"tag":91,"props":7871,"children":7872},{},[7873],{"type":40,"value":601},{"type":34,"tag":91,"props":7875,"children":7876},{"class":93,"line":342},[7877],{"type":34,"tag":91,"props":7878,"children":7879},{},[7880],{"type":40,"value":609},{"type":34,"tag":91,"props":7882,"children":7883},{"class":93,"line":612},[7884],{"type":34,"tag":91,"props":7885,"children":7886},{},[7887],{"type":40,"value":618},{"type":34,"tag":91,"props":7889,"children":7890},{"class":93,"line":621},[7891],{"type":34,"tag":91,"props":7892,"children":7893},{},[7894],{"type":40,"value":627},{"type":34,"tag":91,"props":7896,"children":7897},{"class":93,"line":630},[7898],{"type":34,"tag":91,"props":7899,"children":7900},{},[7901],{"type":40,"value":636},{"type":34,"tag":91,"props":7903,"children":7904},{"class":93,"line":639},[7905],{"type":34,"tag":91,"props":7906,"children":7907},{},[7908],{"type":40,"value":645},{"type":34,"tag":91,"props":7910,"children":7911},{"class":93,"line":648},[7912],{"type":34,"tag":91,"props":7913,"children":7914},{},[7915],{"type":40,"value":578},{"type":34,"tag":91,"props":7917,"children":7918},{"class":93,"line":656},[7919],{"type":34,"tag":91,"props":7920,"children":7921},{"emptyLinePlaceholder":125},[7922],{"type":40,"value":128},{"type":34,"tag":91,"props":7924,"children":7925},{"class":93,"line":664},[7926],{"type":34,"tag":91,"props":7927,"children":7928},{},[7929],{"type":40,"value":670},{"type":34,"tag":91,"props":7931,"children":7932},{"class":93,"line":673},[7933],{"type":34,"tag":91,"props":7934,"children":7935},{},[7936],{"type":40,"value":173},{"type":34,"tag":91,"props":7938,"children":7939},{"class":93,"line":681},[7940],{"type":34,"tag":91,"props":7941,"children":7942},{"emptyLinePlaceholder":125},[7943],{"type":40,"value":128},{"type":34,"tag":91,"props":7945,"children":7946},{"class":93,"line":689},[7947],{"type":34,"tag":91,"props":7948,"children":7949},{},[7950],{"type":40,"value":695},{"type":34,"tag":91,"props":7952,"children":7953},{"class":93,"line":698},[7954],{"type":34,"tag":91,"props":7955,"children":7956},{},[7957],{"type":40,"value":704},{"type":34,"tag":91,"props":7959,"children":7960},{"class":93,"line":707},[7961],{"type":34,"tag":91,"props":7962,"children":7963},{},[7964],{"type":40,"value":713},{"type":34,"tag":91,"props":7966,"children":7967},{"class":93,"line":716},[7968],{"type":34,"tag":91,"props":7969,"children":7970},{},[7971],{"type":40,"value":722},{"type":34,"tag":91,"props":7973,"children":7974},{"class":93,"line":725},[7975],{"type":34,"tag":91,"props":7976,"children":7977},{},[7978],{"type":40,"value":731},{"type":34,"tag":91,"props":7980,"children":7981},{"class":93,"line":734},[7982],{"type":34,"tag":91,"props":7983,"children":7984},{},[7985],{"type":40,"value":601},{"type":34,"tag":91,"props":7987,"children":7988},{"class":93,"line":742},[7989],{"type":34,"tag":91,"props":7990,"children":7991},{},[7992],{"type":40,"value":748},{"type":34,"tag":91,"props":7994,"children":7995},{"class":93,"line":751},[7996],{"type":34,"tag":91,"props":7997,"children":7998},{},[7999],{"type":40,"value":578},{"type":34,"tag":91,"props":8001,"children":8002},{"class":93,"line":759},[8003],{"type":34,"tag":91,"props":8004,"children":8005},{"emptyLinePlaceholder":125},[8006],{"type":40,"value":128},{"type":34,"tag":91,"props":8008,"children":8009},{"class":93,"line":767},[8010],{"type":34,"tag":91,"props":8011,"children":8012},{},[8013],{"type":40,"value":773},{"type":34,"tag":91,"props":8015,"children":8016},{"class":93,"line":776},[8017],{"type":34,"tag":91,"props":8018,"children":8019},{},[8020],{"type":40,"value":782},{"type":34,"tag":91,"props":8022,"children":8023},{"class":93,"line":785},[8024],{"type":34,"tag":91,"props":8025,"children":8026},{},[8027],{"type":40,"value":791},{"type":34,"tag":91,"props":8029,"children":8030},{"class":93,"line":794},[8031],{"type":34,"tag":91,"props":8032,"children":8033},{},[8034],{"type":40,"value":627},{"type":34,"tag":91,"props":8036,"children":8037},{"class":93,"line":802},[8038],{"type":34,"tag":91,"props":8039,"children":8040},{},[8041],{"type":40,"value":578},{"type":34,"tag":91,"props":8043,"children":8044},{"class":93,"line":810},[8045],{"type":34,"tag":91,"props":8046,"children":8047},{},[8048],{"type":40,"value":816},{"type":34,"tag":91,"props":8050,"children":8051},{"class":93,"line":819},[8052],{"type":34,"tag":91,"props":8053,"children":8054},{},[8055],{"type":40,"value":173},{"type":34,"tag":91,"props":8057,"children":8058},{"class":93,"line":827},[8059],{"type":34,"tag":91,"props":8060,"children":8061},{"emptyLinePlaceholder":125},[8062],{"type":40,"value":128},{"type":34,"tag":91,"props":8064,"children":8065},{"class":93,"line":835},[8066],{"type":34,"tag":91,"props":8067,"children":8068},{},[8069],{"type":40,"value":841},{"type":34,"tag":91,"props":8071,"children":8072},{"class":93,"line":844},[8073],{"type":34,"tag":91,"props":8074,"children":8075},{},[8076],{"type":40,"value":850},{"type":34,"tag":91,"props":8078,"children":8079},{"class":93,"line":853},[8080],{"type":34,"tag":91,"props":8081,"children":8082},{},[8083],{"type":40,"value":601},{"type":34,"tag":91,"props":8085,"children":8086},{"class":93,"line":861},[8087],{"type":34,"tag":91,"props":8088,"children":8089},{},[8090],{"type":40,"value":867},{"type":34,"tag":91,"props":8092,"children":8093},{"class":93,"line":870},[8094],{"type":34,"tag":91,"props":8095,"children":8096},{},[8097],{"type":40,"value":876},{"type":34,"tag":91,"props":8099,"children":8100},{"class":93,"line":879},[8101],{"type":34,"tag":91,"props":8102,"children":8103},{},[8104],{"type":40,"value":578},{"type":34,"tag":91,"props":8106,"children":8107},{"class":93,"line":887},[8108],{"type":34,"tag":91,"props":8109,"children":8110},{"emptyLinePlaceholder":125},[8111],{"type":40,"value":128},{"type":34,"tag":91,"props":8113,"children":8114},{"class":93,"line":895},[8115],{"type":34,"tag":91,"props":8116,"children":8117},{},[8118],{"type":40,"value":901},{"type":34,"tag":91,"props":8120,"children":8121},{"class":93,"line":904},[8122],{"type":34,"tag":91,"props":8123,"children":8124},{},[8125],{"type":40,"value":910},{"type":34,"tag":91,"props":8127,"children":8128},{"class":93,"line":913},[8129],{"type":34,"tag":91,"props":8130,"children":8131},{},[8132],{"type":40,"value":919},{"type":34,"tag":91,"props":8134,"children":8135},{"class":93,"line":922},[8136],{"type":34,"tag":91,"props":8137,"children":8138},{},[8139],{"type":40,"value":928},{"type":34,"tag":91,"props":8141,"children":8142},{"class":93,"line":931},[8143],{"type":34,"tag":91,"props":8144,"children":8145},{},[8146],{"type":40,"value":937},{"type":34,"tag":91,"props":8148,"children":8149},{"class":93,"line":940},[8150],{"type":34,"tag":91,"props":8151,"children":8152},{},[8153],{"type":40,"value":946},{"type":34,"tag":91,"props":8155,"children":8156},{"class":93,"line":949},[8157],{"type":34,"tag":91,"props":8158,"children":8159},{},[8160],{"type":40,"value":955},{"type":34,"tag":91,"props":8162,"children":8163},{"class":93,"line":958},[8164],{"type":34,"tag":91,"props":8165,"children":8166},{},[8167],{"type":40,"value":964},{"type":34,"tag":91,"props":8169,"children":8170},{"class":93,"line":967},[8171],{"type":34,"tag":91,"props":8172,"children":8173},{},[8174],{"type":40,"value":946},{"type":34,"tag":91,"props":8176,"children":8177},{"class":93,"line":975},[8178],{"type":34,"tag":91,"props":8179,"children":8180},{},[8181],{"type":40,"value":981},{"type":34,"tag":91,"props":8183,"children":8184},{"class":93,"line":984},[8185],{"type":34,"tag":91,"props":8186,"children":8187},{"emptyLinePlaceholder":125},[8188],{"type":40,"value":128},{"type":34,"tag":91,"props":8190,"children":8191},{"class":93,"line":992},[8192],{"type":34,"tag":91,"props":8193,"children":8194},{},[8195],{"type":40,"value":998},{"type":34,"tag":91,"props":8197,"children":8198},{"class":93,"line":1001},[8199],{"type":34,"tag":91,"props":8200,"children":8201},{"emptyLinePlaceholder":125},[8202],{"type":40,"value":128},{"type":34,"tag":91,"props":8204,"children":8205},{"class":93,"line":1009},[8206],{"type":34,"tag":91,"props":8207,"children":8208},{},[8209],{"type":40,"value":1015},{"type":34,"tag":91,"props":8211,"children":8212},{"class":93,"line":1018},[8213],{"type":34,"tag":91,"props":8214,"children":8215},{},[8216],{"type":40,"value":1024},{"type":34,"tag":91,"props":8218,"children":8219},{"class":93,"line":1027},[8220],{"type":34,"tag":91,"props":8221,"children":8222},{},[8223],{"type":40,"value":1033},{"type":34,"tag":91,"props":8225,"children":8226},{"class":93,"line":1036},[8227],{"type":34,"tag":91,"props":8228,"children":8229},{},[8230],{"type":40,"value":578},{"type":34,"tag":91,"props":8232,"children":8233},{"class":93,"line":1044},[8234],{"type":34,"tag":91,"props":8235,"children":8236},{},[8237],{"type":40,"value":173},{"type":34,"tag":43,"props":8239,"children":8240},{},[8241,8242,8247],{"type":40,"value":1054},{"type":34,"tag":49,"props":8243,"children":8245},{"className":8244},[],[8246],{"type":40,"value":1060},{"type":40,"value":1062},{"type":34,"tag":35,"props":8249,"children":8250},{"id":1065},[8251],{"type":40,"value":1068},{"type":34,"tag":43,"props":8253,"children":8254},{},[8255],{"type":40,"value":1073},{"type":34,"tag":81,"props":8257,"children":8258},{"className":377,"code":1076,"language":379,"meta":7,"style":7},[8259],{"type":34,"tag":49,"props":8260,"children":8261},{"__ignoreMap":7},[8262,8269,8276,8283,8290,8297,8304,8311,8318,8325,8332,8339,8346,8353,8360,8367,8374,8381,8388,8395,8402,8409,8416,8423,8430,8437,8444,8451,8458,8465,8472,8479,8486,8493,8500,8507],{"type":34,"tag":91,"props":8263,"children":8264},{"class":93,"line":94},[8265],{"type":34,"tag":91,"props":8266,"children":8267},{},[8268],{"type":40,"value":1088},{"type":34,"tag":91,"props":8270,"children":8271},{"class":93,"line":103},[8272],{"type":34,"tag":91,"props":8273,"children":8274},{"emptyLinePlaceholder":125},[8275],{"type":40,"value":128},{"type":34,"tag":91,"props":8277,"children":8278},{"class":93,"line":112},[8279],{"type":34,"tag":91,"props":8280,"children":8281},{},[8282],{"type":40,"value":1103},{"type":34,"tag":91,"props":8284,"children":8285},{"class":93,"line":121},[8286],{"type":34,"tag":91,"props":8287,"children":8288},{},[8289],{"type":40,"value":1111},{"type":34,"tag":91,"props":8291,"children":8292},{"class":93,"line":131},[8293],{"type":34,"tag":91,"props":8294,"children":8295},{},[8296],{"type":40,"value":1119},{"type":34,"tag":91,"props":8298,"children":8299},{"class":93,"line":140},[8300],{"type":34,"tag":91,"props":8301,"children":8302},{},[8303],{"type":40,"value":173},{"type":34,"tag":91,"props":8305,"children":8306},{"class":93,"line":149},[8307],{"type":34,"tag":91,"props":8308,"children":8309},{"emptyLinePlaceholder":125},[8310],{"type":40,"value":128},{"type":34,"tag":91,"props":8312,"children":8313},{"class":93,"line":158},[8314],{"type":34,"tag":91,"props":8315,"children":8316},{},[8317],{"type":40,"value":1141},{"type":34,"tag":91,"props":8319,"children":8320},{"class":93,"line":167},[8321],{"type":34,"tag":91,"props":8322,"children":8323},{},[8324],{"type":40,"value":1149},{"type":34,"tag":91,"props":8326,"children":8327},{"class":93,"line":176},[8328],{"type":34,"tag":91,"props":8329,"children":8330},{},[8331],{"type":40,"value":1157},{"type":34,"tag":91,"props":8333,"children":8334},{"class":93,"line":184},[8335],{"type":34,"tag":91,"props":8336,"children":8337},{},[8338],{"type":40,"value":1165},{"type":34,"tag":91,"props":8340,"children":8341},{"class":93,"line":193},[8342],{"type":34,"tag":91,"props":8343,"children":8344},{},[8345],{"type":40,"value":1173},{"type":34,"tag":91,"props":8347,"children":8348},{"class":93,"line":202},[8349],{"type":34,"tag":91,"props":8350,"children":8351},{},[8352],{"type":40,"value":1181},{"type":34,"tag":91,"props":8354,"children":8355},{"class":93,"line":210},[8356],{"type":34,"tag":91,"props":8357,"children":8358},{},[8359],{"type":40,"value":1189},{"type":34,"tag":91,"props":8361,"children":8362},{"class":93,"line":218},[8363],{"type":34,"tag":91,"props":8364,"children":8365},{},[8366],{"type":40,"value":1197},{"type":34,"tag":91,"props":8368,"children":8369},{"class":93,"line":227},[8370],{"type":34,"tag":91,"props":8371,"children":8372},{},[8373],{"type":40,"value":1205},{"type":34,"tag":91,"props":8375,"children":8376},{"class":93,"line":236},[8377],{"type":34,"tag":91,"props":8378,"children":8379},{},[8380],{"type":40,"value":1213},{"type":34,"tag":91,"props":8382,"children":8383},{"class":93,"line":245},[8384],{"type":34,"tag":91,"props":8385,"children":8386},{},[8387],{"type":40,"value":1221},{"type":34,"tag":91,"props":8389,"children":8390},{"class":93,"line":254},[8391],{"type":34,"tag":91,"props":8392,"children":8393},{},[8394],{"type":40,"value":1197},{"type":34,"tag":91,"props":8396,"children":8397},{"class":93,"line":262},[8398],{"type":34,"tag":91,"props":8399,"children":8400},{},[8401],{"type":40,"value":1236},{"type":34,"tag":91,"props":8403,"children":8404},{"class":93,"line":270},[8405],{"type":34,"tag":91,"props":8406,"children":8407},{},[8408],{"type":40,"value":1244},{"type":34,"tag":91,"props":8410,"children":8411},{"class":93,"line":279},[8412],{"type":34,"tag":91,"props":8413,"children":8414},{"emptyLinePlaceholder":125},[8415],{"type":40,"value":128},{"type":34,"tag":91,"props":8417,"children":8418},{"class":93,"line":288},[8419],{"type":34,"tag":91,"props":8420,"children":8421},{},[8422],{"type":40,"value":1259},{"type":34,"tag":91,"props":8424,"children":8425},{"class":93,"line":297},[8426],{"type":34,"tag":91,"props":8427,"children":8428},{},[8429],{"type":40,"value":1267},{"type":34,"tag":91,"props":8431,"children":8432},{"class":93,"line":306},[8433],{"type":34,"tag":91,"props":8434,"children":8435},{},[8436],{"type":40,"value":1275},{"type":34,"tag":91,"props":8438,"children":8439},{"class":93,"line":315},[8440],{"type":34,"tag":91,"props":8441,"children":8442},{},[8443],{"type":40,"value":578},{"type":34,"tag":91,"props":8445,"children":8446},{"class":93,"line":324},[8447],{"type":34,"tag":91,"props":8448,"children":8449},{},[8450],{"type":40,"value":173},{"type":34,"tag":91,"props":8452,"children":8453},{"class":93,"line":333},[8454],{"type":34,"tag":91,"props":8455,"children":8456},{"emptyLinePlaceholder":125},[8457],{"type":40,"value":128},{"type":34,"tag":91,"props":8459,"children":8460},{"class":93,"line":342},[8461],{"type":34,"tag":91,"props":8462,"children":8463},{},[8464],{"type":40,"value":1304},{"type":34,"tag":91,"props":8466,"children":8467},{"class":93,"line":612},[8468],{"type":34,"tag":91,"props":8469,"children":8470},{},[8471],{"type":40,"value":538},{"type":34,"tag":91,"props":8473,"children":8474},{"class":93,"line":621},[8475],{"type":34,"tag":91,"props":8476,"children":8477},{},[8478],{"type":40,"value":546},{"type":34,"tag":91,"props":8480,"children":8481},{"class":93,"line":630},[8482],{"type":34,"tag":91,"props":8483,"children":8484},{},[8485],{"type":40,"value":554},{"type":34,"tag":91,"props":8487,"children":8488},{"class":93,"line":639},[8489],{"type":34,"tag":91,"props":8490,"children":8491},{},[8492],{"type":40,"value":1333},{"type":34,"tag":91,"props":8494,"children":8495},{"class":93,"line":648},[8496],{"type":34,"tag":91,"props":8497,"children":8498},{},[8499],{"type":40,"value":1341},{"type":34,"tag":91,"props":8501,"children":8502},{"class":93,"line":656},[8503],{"type":34,"tag":91,"props":8504,"children":8505},{},[8506],{"type":40,"value":1244},{"type":34,"tag":91,"props":8508,"children":8509},{"class":93,"line":664},[8510],{"type":34,"tag":91,"props":8511,"children":8512},{},[8513],{"type":40,"value":173},{"type":34,"tag":35,"props":8515,"children":8516},{"id":1358},[8517],{"type":40,"value":1361},{"type":34,"tag":43,"props":8519,"children":8520},{},[8521],{"type":40,"value":1366},{"type":34,"tag":81,"props":8523,"children":8524},{"className":377,"code":1369,"language":379,"meta":7,"style":7},[8525],{"type":34,"tag":49,"props":8526,"children":8527},{"__ignoreMap":7},[8528,8535,8542,8549,8556,8563,8570,8577,8584,8591,8598,8605,8612,8619,8626,8633,8640,8647],{"type":34,"tag":91,"props":8529,"children":8530},{"class":93,"line":94},[8531],{"type":34,"tag":91,"props":8532,"children":8533},{},[8534],{"type":40,"value":1381},{"type":34,"tag":91,"props":8536,"children":8537},{"class":93,"line":103},[8538],{"type":34,"tag":91,"props":8539,"children":8540},{},[8541],{"type":40,"value":1389},{"type":34,"tag":91,"props":8543,"children":8544},{"class":93,"line":112},[8545],{"type":34,"tag":91,"props":8546,"children":8547},{"emptyLinePlaceholder":125},[8548],{"type":40,"value":128},{"type":34,"tag":91,"props":8550,"children":8551},{"class":93,"line":121},[8552],{"type":34,"tag":91,"props":8553,"children":8554},{},[8555],{"type":40,"value":1404},{"type":34,"tag":91,"props":8557,"children":8558},{"class":93,"line":131},[8559],{"type":34,"tag":91,"props":8560,"children":8561},{},[8562],{"type":40,"value":1412},{"type":34,"tag":91,"props":8564,"children":8565},{"class":93,"line":140},[8566],{"type":34,"tag":91,"props":8567,"children":8568},{},[8569],{"type":40,"value":1420},{"type":34,"tag":91,"props":8571,"children":8572},{"class":93,"line":149},[8573],{"type":34,"tag":91,"props":8574,"children":8575},{},[8576],{"type":40,"value":1428},{"type":34,"tag":91,"props":8578,"children":8579},{"class":93,"line":158},[8580],{"type":34,"tag":91,"props":8581,"children":8582},{},[8583],{"type":40,"value":1436},{"type":34,"tag":91,"props":8585,"children":8586},{"class":93,"line":167},[8587],{"type":34,"tag":91,"props":8588,"children":8589},{},[8590],{"type":40,"value":578},{"type":34,"tag":91,"props":8592,"children":8593},{"class":93,"line":176},[8594],{"type":34,"tag":91,"props":8595,"children":8596},{"emptyLinePlaceholder":125},[8597],{"type":40,"value":128},{"type":34,"tag":91,"props":8599,"children":8600},{"class":93,"line":184},[8601],{"type":34,"tag":91,"props":8602,"children":8603},{},[8604],{"type":40,"value":1458},{"type":34,"tag":91,"props":8606,"children":8607},{"class":93,"line":193},[8608],{"type":34,"tag":91,"props":8609,"children":8610},{},[8611],{"type":40,"value":1466},{"type":34,"tag":91,"props":8613,"children":8614},{"class":93,"line":202},[8615],{"type":34,"tag":91,"props":8616,"children":8617},{},[8618],{"type":40,"value":1474},{"type":34,"tag":91,"props":8620,"children":8621},{"class":93,"line":210},[8622],{"type":34,"tag":91,"props":8623,"children":8624},{},[8625],{"type":40,"value":1482},{"type":34,"tag":91,"props":8627,"children":8628},{"class":93,"line":218},[8629],{"type":34,"tag":91,"props":8630,"children":8631},{},[8632],{"type":40,"value":1490},{"type":34,"tag":91,"props":8634,"children":8635},{"class":93,"line":227},[8636],{"type":34,"tag":91,"props":8637,"children":8638},{},[8639],{"type":40,"value":1498},{"type":34,"tag":91,"props":8641,"children":8642},{"class":93,"line":236},[8643],{"type":34,"tag":91,"props":8644,"children":8645},{},[8646],{"type":40,"value":1244},{"type":34,"tag":91,"props":8648,"children":8649},{"class":93,"line":245},[8650],{"type":34,"tag":91,"props":8651,"children":8652},{},[8653],{"type":40,"value":173},{"type":34,"tag":43,"props":8655,"children":8656},{},[8657,8658,8663],{"type":40,"value":1517},{"type":34,"tag":49,"props":8659,"children":8661},{"className":8660},[],[8662],{"type":40,"value":1523},{"type":40,"value":1525},{"type":34,"tag":35,"props":8665,"children":8666},{"id":1528},[8667],{"type":40,"value":1531},{"type":34,"tag":43,"props":8669,"children":8670},{},[8671],{"type":40,"value":1536},{"type":34,"tag":81,"props":8673,"children":8674},{"className":377,"code":1539,"language":379,"meta":7,"style":7},[8675],{"type":34,"tag":49,"props":8676,"children":8677},{"__ignoreMap":7},[8678,8685,8692,8699,8706,8713,8720,8727,8734,8741,8748,8755,8762,8769,8776,8783,8790,8797,8804,8811,8818,8825,8832,8839],{"type":34,"tag":91,"props":8679,"children":8680},{"class":93,"line":94},[8681],{"type":34,"tag":91,"props":8682,"children":8683},{},[8684],{"type":40,"value":1551},{"type":34,"tag":91,"props":8686,"children":8687},{"class":93,"line":103},[8688],{"type":34,"tag":91,"props":8689,"children":8690},{},[8691],{"type":40,"value":1559},{"type":34,"tag":91,"props":8693,"children":8694},{"class":93,"line":112},[8695],{"type":34,"tag":91,"props":8696,"children":8697},{},[8698],{"type":40,"value":1567},{"type":34,"tag":91,"props":8700,"children":8701},{"class":93,"line":121},[8702],{"type":34,"tag":91,"props":8703,"children":8704},{},[8705],{"type":40,"value":1575},{"type":34,"tag":91,"props":8707,"children":8708},{"class":93,"line":131},[8709],{"type":34,"tag":91,"props":8710,"children":8711},{},[8712],{"type":40,"value":1583},{"type":34,"tag":91,"props":8714,"children":8715},{"class":93,"line":140},[8716],{"type":34,"tag":91,"props":8717,"children":8718},{},[8719],{"type":40,"value":981},{"type":34,"tag":91,"props":8721,"children":8722},{"class":93,"line":149},[8723],{"type":34,"tag":91,"props":8724,"children":8725},{"emptyLinePlaceholder":125},[8726],{"type":40,"value":128},{"type":34,"tag":91,"props":8728,"children":8729},{"class":93,"line":158},[8730],{"type":34,"tag":91,"props":8731,"children":8732},{},[8733],{"type":40,"value":1605},{"type":34,"tag":91,"props":8735,"children":8736},{"class":93,"line":167},[8737],{"type":34,"tag":91,"props":8738,"children":8739},{},[8740],{"type":40,"value":1613},{"type":34,"tag":91,"props":8742,"children":8743},{"class":93,"line":176},[8744],{"type":34,"tag":91,"props":8745,"children":8746},{},[8747],{"type":40,"value":1621},{"type":34,"tag":91,"props":8749,"children":8750},{"class":93,"line":184},[8751],{"type":34,"tag":91,"props":8752,"children":8753},{},[8754],{"type":40,"value":1629},{"type":34,"tag":91,"props":8756,"children":8757},{"class":93,"line":193},[8758],{"type":34,"tag":91,"props":8759,"children":8760},{},[8761],{"type":40,"value":1637},{"type":34,"tag":91,"props":8763,"children":8764},{"class":93,"line":202},[8765],{"type":34,"tag":91,"props":8766,"children":8767},{},[8768],{"type":40,"value":1645},{"type":34,"tag":91,"props":8770,"children":8771},{"class":93,"line":210},[8772],{"type":34,"tag":91,"props":8773,"children":8774},{},[8775],{"type":40,"value":1653},{"type":34,"tag":91,"props":8777,"children":8778},{"class":93,"line":218},[8779],{"type":34,"tag":91,"props":8780,"children":8781},{},[8782],{"type":40,"value":981},{"type":34,"tag":91,"props":8784,"children":8785},{"class":93,"line":227},[8786],{"type":34,"tag":91,"props":8787,"children":8788},{"emptyLinePlaceholder":125},[8789],{"type":40,"value":128},{"type":34,"tag":91,"props":8791,"children":8792},{"class":93,"line":236},[8793],{"type":34,"tag":91,"props":8794,"children":8795},{},[8796],{"type":40,"value":1675},{"type":34,"tag":91,"props":8798,"children":8799},{"class":93,"line":245},[8800],{"type":34,"tag":91,"props":8801,"children":8802},{},[8803],{"type":40,"value":1683},{"type":34,"tag":91,"props":8805,"children":8806},{"class":93,"line":254},[8807],{"type":34,"tag":91,"props":8808,"children":8809},{"emptyLinePlaceholder":125},[8810],{"type":40,"value":128},{"type":34,"tag":91,"props":8812,"children":8813},{"class":93,"line":262},[8814],{"type":34,"tag":91,"props":8815,"children":8816},{},[8817],{"type":40,"value":1698},{"type":34,"tag":91,"props":8819,"children":8820},{"class":93,"line":270},[8821],{"type":34,"tag":91,"props":8822,"children":8823},{},[8824],{"type":40,"value":1706},{"type":34,"tag":91,"props":8826,"children":8827},{"class":93,"line":279},[8828],{"type":34,"tag":91,"props":8829,"children":8830},{"emptyLinePlaceholder":125},[8831],{"type":40,"value":128},{"type":34,"tag":91,"props":8833,"children":8834},{"class":93,"line":288},[8835],{"type":34,"tag":91,"props":8836,"children":8837},{},[8838],{"type":40,"value":1721},{"type":34,"tag":91,"props":8840,"children":8841},{"class":93,"line":297},[8842],{"type":34,"tag":91,"props":8843,"children":8844},{},[8845],{"type":40,"value":173},{"type":34,"tag":43,"props":8847,"children":8848},{},[8849,8850,8855],{"type":40,"value":1733},{"type":34,"tag":49,"props":8851,"children":8853},{"className":8852},[],[8854],{"type":40,"value":1739},{"type":40,"value":1741},{"type":34,"tag":35,"props":8857,"children":8858},{"id":1744},[8859],{"type":40,"value":1747},{"type":34,"tag":43,"props":8861,"children":8862},{},[8863,8864,8869],{"type":40,"value":1752},{"type":34,"tag":49,"props":8865,"children":8867},{"className":8866},[],[8868],{"type":40,"value":1758},{"type":40,"value":1760},{"type":34,"tag":1762,"props":8871,"children":8872},{},[8873,8881,8889,8897],{"type":34,"tag":1766,"props":8874,"children":8875},{},[8876,8880],{"type":34,"tag":1770,"props":8877,"children":8878},{},[8879],{"type":40,"value":1774},{"type":40,"value":1776},{"type":34,"tag":1766,"props":8882,"children":8883},{},[8884,8888],{"type":34,"tag":1770,"props":8885,"children":8886},{},[8887],{"type":40,"value":1784},{"type":40,"value":1786},{"type":34,"tag":1766,"props":8890,"children":8891},{},[8892,8896],{"type":34,"tag":1770,"props":8893,"children":8894},{},[8895],{"type":40,"value":1794},{"type":40,"value":1796},{"type":34,"tag":1766,"props":8898,"children":8899},{},[8900,8904],{"type":34,"tag":1770,"props":8901,"children":8902},{},[8903],{"type":40,"value":1804},{"type":40,"value":1806},{"type":34,"tag":43,"props":8906,"children":8907},{},[8908],{"type":40,"value":1811},{"type":34,"tag":43,"props":8910,"children":8911},{},[8912],{"type":40,"value":1816},{"type":34,"tag":43,"props":8914,"children":8915},{},[8916],{"type":40,"value":1821},{"type":34,"tag":1823,"props":8918,"children":8919},{},[8920],{"type":40,"value":1827},{"title":7,"searchDepth":112,"depth":112,"links":8922},[8923,8924,8925,8926,8927,8928,8929],{"id":37,"depth":103,"text":41},{"id":64,"depth":103,"text":67},{"id":371,"depth":103,"text":374},{"id":1065,"depth":103,"text":1068},{"id":1358,"depth":103,"text":1361},{"id":1528,"depth":103,"text":1531},{"id":1744,"depth":103,"text":1747},1777018791107]