[{"data":1,"prerenderedAt":1521},["ShallowReactive",2],{"navigation_docs":3,"-engineering-deployment-ecs-langfuse-deployment":348,"-engineering-deployment-ecs-langfuse-deployment-surround":1516},[4,8,68,98,216,245,259,280,344],{"title":5,"path":6,"stem":7},"Introduction","\u002Fintroduction","0.introduction",{"title":9,"icon":10,"path":11,"stem":12,"children":13,"page":63},"Company","i-lucide-building-2","\u002Fcompany","1.company",[14,18,22,26,30,34,38,42,46,50,64],{"title":15,"path":16,"stem":17},"About","\u002Fcompany\u002Fabout","1.company\u002F0.about",{"title":19,"path":20,"stem":21},"Values","\u002Fcompany\u002Fvalues","1.company\u002F1.values",{"title":23,"path":24,"stem":25},"Communication","\u002Fcompany\u002Fcommunication","1.company\u002Fcommunication",{"title":27,"path":28,"stem":29},"Competition","\u002Fcompany\u002Fcompetition","1.company\u002Fcompetition",{"title":31,"path":32,"stem":33},"Hybrid Working","\u002Fcompany\u002Fhybrid-working","1.company\u002Fhybrid-working",{"title":35,"path":36,"stem":37},"Manchester Office","\u002Fcompany\u002Foffice","1.company\u002Foffice",{"title":39,"path":40,"stem":41},"Operations","\u002Fcompany\u002Foperations","1.company\u002Foperations",{"title":43,"path":44,"stem":45},"Policies","\u002Fcompany\u002Fpolicies","1.company\u002Fpolicies",{"title":47,"path":48,"stem":49},"Product Strategy","\u002Fcompany\u002Fproduct-strategy","1.company\u002Fproduct-strategy",{"title":51,"path":52,"stem":53,"children":54,"page":63},"Products","\u002Fcompany\u002Fproducts","1.company\u002Fproducts",[55,59],{"title":56,"path":57,"stem":58},"Capability Exchange","\u002Fcompany\u002Fproducts\u002Fcapability-exchange","1.company\u002Fproducts\u002Fcapability-exchange",{"title":60,"path":61,"stem":62},"ESProfiler Platform","\u002Fcompany\u002Fproducts\u002Fesprofiler","1.company\u002Fproducts\u002Fesprofiler",false,{"title":65,"path":66,"stem":67},"Security","\u002Fcompany\u002Fsecurity","1.company\u002Fsecurity",{"title":69,"icon":70,"path":71,"stem":72,"children":73,"page":63},"People Ops","i-lucide-users","\u002Fpeople-ops","2.people-ops",[74,78,82,86,90,94],{"title":75,"path":76,"stem":77},"Compensation","\u002Fpeople-ops\u002Fcompensation","2.people-ops\u002Fcompensation",{"title":79,"path":80,"stem":81},"Education","\u002Fpeople-ops\u002Feducation","2.people-ops\u002Feducation",{"title":83,"path":84,"stem":85},"Expenses","\u002Fpeople-ops\u002Fexpenses","2.people-ops\u002Fexpenses",{"title":87,"path":88,"stem":89},"Holiday & Leave","\u002Fpeople-ops\u002Fleave","2.people-ops\u002Fleave",{"title":91,"path":92,"stem":93},"Onboarding","\u002Fpeople-ops\u002Fonboarding","2.people-ops\u002Fonboarding",{"title":95,"path":96,"stem":97},"Recruitment","\u002Fpeople-ops\u002Frecruitment","2.people-ops\u002Frecruitment",{"title":99,"icon":100,"path":101,"stem":102,"children":103,"page":63},"Engineering","i-lucide-rocket","\u002Fengineering","3.engineering",[104,147,151,171,192,196,204,208,212],{"title":105,"path":106,"stem":107,"children":108,"page":63},"Contributing","\u002Fengineering\u002Fcontributing","3.engineering\u002Fcontributing",[109,113,117,121,125,138],{"title":110,"path":111,"stem":112},"Development Setup","\u002Fengineering\u002Fcontributing\u002Fdevelopment-setup","3.engineering\u002Fcontributing\u002F1.development-setup",{"title":114,"path":115,"stem":116},"Engineering Operations","\u002Fengineering\u002Fcontributing\u002Fengineering-operations","3.engineering\u002Fcontributing\u002F2.engineering-operations",{"title":118,"path":119,"stem":120},"Documentation","\u002Fengineering\u002Fcontributing\u002Fdocumentation","3.engineering\u002Fcontributing\u002F3.documentation",{"title":122,"path":123,"stem":124},"Agentic Coding","\u002Fengineering\u002Fcontributing\u002Fagentic-coding","3.engineering\u002Fcontributing\u002Fagentic-coding",{"title":126,"path":127,"stem":128,"children":129,"page":63},"Back End","\u002Fengineering\u002Fcontributing\u002Fback-end","3.engineering\u002Fcontributing\u002Fback-end",[130,134],{"title":131,"path":132,"stem":133},"API Guidelines","\u002Fengineering\u002Fcontributing\u002Fback-end\u002Fapi-guidelines","3.engineering\u002Fcontributing\u002Fback-end\u002Fapi-guidelines",{"title":135,"path":136,"stem":137},"LLM Prompts & Langfuse Integration","\u002Fengineering\u002Fcontributing\u002Fback-end\u002Fllm-prompts","3.engineering\u002Fcontributing\u002Fback-end\u002Fllm-prompts",{"title":139,"path":140,"stem":141,"children":142,"page":63},"Front End","\u002Fengineering\u002Fcontributing\u002Ffront-end","3.engineering\u002Fcontributing\u002Ffront-end",[143],{"title":144,"path":145,"stem":146},"Testing","\u002Fengineering\u002Fcontributing\u002Ffront-end\u002Ftesting","3.engineering\u002Fcontributing\u002Ffront-end\u002Ftesting",{"title":148,"path":149,"stem":150},"Production Database","\u002Fengineering\u002Fdatabase-connection","3.engineering\u002Fdatabase-connection",{"title":152,"path":153,"stem":154,"children":155},"Deployment","\u002Fengineering\u002Fdeployment","3.engineering\u002Fdeployment",[156,159,163,167],{"title":56,"path":157,"stem":158},"\u002Fengineering\u002Fdeployment\u002Fcapability-exchange","3.engineering\u002Fdeployment\u002Fcapability-exchange",{"title":160,"path":161,"stem":162},"Langfuse Deployment","\u002Fengineering\u002Fdeployment\u002Fecs-langfuse-deployment","3.engineering\u002Fdeployment\u002Fecs-langfuse-deployment",{"title":164,"path":165,"stem":166},"ESP Platform Configuration","\u002Fengineering\u002Fdeployment\u002Fesp-platform-configuration","3.engineering\u002Fdeployment\u002Fesp-platform-configuration",{"title":168,"path":169,"stem":170},"Platform","\u002Fengineering\u002Fdeployment\u002Fplatform","3.engineering\u002Fdeployment\u002Fplatform",{"title":172,"path":173,"stem":174,"children":175,"page":63},"Github","\u002Fengineering\u002Fgithub","3.engineering\u002Fgithub",[176,180,184,188],{"title":177,"path":178,"stem":179},"Packages","\u002Fengineering\u002Fgithub\u002Fpackages","3.engineering\u002Fgithub\u002Fpackages",{"title":181,"path":182,"stem":183},"Personal Access Token","\u002Fengineering\u002Fgithub\u002Fpersonal-access-token","3.engineering\u002Fgithub\u002Fpersonal-access-token",{"title":185,"path":186,"stem":187},"Troubleshooting","\u002Fengineering\u002Fgithub\u002Ftroubleshooting","3.engineering\u002Fgithub\u002Ftroubleshooting",{"title":189,"path":190,"stem":191},"Workflows","\u002Fengineering\u002Fgithub\u002Fworkflows","3.engineering\u002Fgithub\u002Fworkflows",{"title":193,"path":194,"stem":195},"Platform Ops","\u002Fengineering\u002Fplatform-ops","3.engineering\u002Fplatform-ops",{"title":168,"path":197,"stem":198,"children":199,"page":63},"\u002Fengineering\u002Fplatform","3.engineering\u002Fplatform",[200],{"title":201,"path":202,"stem":203},"useAPI","\u002Fengineering\u002Fplatform\u002Fuse-api","3.engineering\u002Fplatform\u002Fuse-api",{"title":205,"path":206,"stem":207},"Project Management","\u002Fengineering\u002Fproject-management","3.engineering\u002Fproject-management",{"title":209,"path":210,"stem":211},"Releases","\u002Fengineering\u002Frelease","3.engineering\u002Frelease",{"title":213,"path":214,"stem":215},"Tools","\u002Fengineering\u002Ftools","3.engineering\u002Ftools",{"title":217,"icon":218,"path":219,"stem":220,"children":221,"page":63},"Design","i-lucide-palette","\u002Fdesign","4.design",[222,226,230,234,238,241],{"title":223,"path":224,"stem":225},"Design Thinking","\u002Fdesign\u002Fdesign-thinking","4.design\u002F1.design-thinking",{"title":227,"path":228,"stem":229},"Figma","\u002Fdesign\u002Ffigma-structure","4.design\u002F2.figma-structure",{"title":231,"path":232,"stem":233},"Design & Development","\u002Fdesign\u002Fdesign-and-development","4.design\u002F3.design-and-development",{"title":235,"path":236,"stem":237},"Branding","\u002Fdesign\u002Fbranding","4.design\u002F4.branding",{"title":213,"path":239,"stem":240},"\u002Fdesign\u002Ftools","4.design\u002F5.tools",{"title":242,"path":243,"stem":244},"Customer Success","\u002Fdesign\u002Fworking-with-customers","4.design\u002F6.working-with-customers",{"title":246,"icon":247,"path":248,"stem":249,"children":250,"page":63},"Sales","i-lucide-dollar-sign","\u002Fsales","4.sales",[251,255],{"title":252,"path":253,"stem":254},"Customer Onboarding","\u002Fsales\u002Fonboarding","4.sales\u002Fonboarding",{"title":256,"path":257,"stem":258},"Sales Tools","\u002Fsales\u002Ftools","4.sales\u002Ftools",{"title":260,"icon":261,"path":262,"stem":263,"children":264,"page":63},"Marketing","i-lucide-book-image","\u002Fmarketing","5.marketing",[265,269,273,276],{"title":266,"path":267,"stem":268},"Content","\u002Fmarketing\u002Fcontent","5.marketing\u002Fcontent",{"title":270,"path":271,"stem":272},"Messaging","\u002Fmarketing\u002Fmessaging","5.marketing\u002Fmessaging",{"title":213,"path":274,"stem":275},"\u002Fmarketing\u002Ftools","5.marketing\u002Ftools",{"title":277,"path":278,"stem":279},"Website","\u002Fmarketing\u002Fwebsite","5.marketing\u002Fwebsite",{"title":281,"icon":282,"path":283,"stem":284,"children":285,"page":63},"AI & Data Ops","i-lucide-database","\u002Fdata-ops","6.data-ops",[286,294,298,323,340],{"title":56,"path":287,"stem":288,"children":289,"page":63},"\u002Fdata-ops\u002Fcapability-exchange","6.data-ops\u002FCapability Exchange",[290],{"title":291,"path":292,"stem":293},"Leaderboard Calculation","\u002Fdata-ops\u002Fcapability-exchange\u002Fleaderboard-calculation","6.data-ops\u002FCapability Exchange\u002Fleaderboard-calculation",{"title":295,"path":296,"stem":297},"Account Portal (CAS)","\u002Fdata-ops\u002Faccount-portal","6.data-ops\u002Faccount-portal",{"title":299,"path":300,"stem":301,"children":302,"page":63},"Data Management","\u002Fdata-ops\u002Fdata-management","6.data-ops\u002Fdata-management",[303,307,311,315,319],{"title":304,"path":305,"stem":306},"Adding Products","\u002Fdata-ops\u002Fdata-management\u002Fadding-products","6.data-ops\u002Fdata-management\u002Fadding-products",{"title":308,"path":309,"stem":310},"Adding Vendors","\u002Fdata-ops\u002Fdata-management\u002Fadding-vendors","6.data-ops\u002Fdata-management\u002Fadding-vendors",{"title":312,"path":313,"stem":314},"Framework Mapping","\u002Fdata-ops\u002Fdata-management\u002Fframework-mapping","6.data-ops\u002Fdata-management\u002Fframework-mapping",{"title":316,"path":317,"stem":318},"Refreshing Vendors","\u002Fdata-ops\u002Fdata-management\u002Frefreshing-vendors","6.data-ops\u002Fdata-management\u002Frefreshing-vendors",{"title":320,"path":321,"stem":322},"Reviewing Draft Vendors","\u002Fdata-ops\u002Fdata-management\u002Freviewing-draft-vendors","6.data-ops\u002Fdata-management\u002Freviewing-draft-vendors",{"title":324,"path":325,"stem":326,"children":327,"page":63},"LLM Ops","\u002Fdata-ops\u002Fllm-ops","6.data-ops\u002Fllm-ops",[328,332,336],{"title":329,"path":330,"stem":331},"Agents","\u002Fdata-ops\u002Fllm-ops\u002Fagents","6.data-ops\u002Fllm-ops\u002F1.agents",{"title":333,"path":334,"stem":335},"ESPi Architecture & Query Flow","\u002Fdata-ops\u002Fllm-ops\u002Fespi-architecture","6.data-ops\u002Fllm-ops\u002F2.espi-architecture",{"title":337,"path":338,"stem":339},"Evaluating Agents","\u002Fdata-ops\u002Fllm-ops\u002Fevaluations","6.data-ops\u002Fllm-ops\u002F3.evaluations",{"title":341,"path":342,"stem":343},"Message Queues","\u002Fdata-ops\u002Fmessage-queues","6.data-ops\u002Fmessage-queues",{"title":345,"path":346,"stem":347},"Glossary","\u002Fglossary","glossary",{"id":349,"title":160,"body":350,"description":1510,"extension":1511,"links":1512,"meta":1513,"navigation":1348,"path":161,"seo":1514,"stem":162,"__hash__":1515},"docs\u002F3.engineering\u002Fdeployment\u002Fecs-langfuse-deployment.md",{"type":351,"value":352,"toc":1492},"minimark",[353,365,373,376,390,393,398,405,416,488,490,494,497,502,525,529,532,573,578,763,765,769,772,847,904,977,979,983,986,990,1089,1093,1100,1144,1150,1152,1156,1159,1222,1224,1228,1231,1234,1298,1300,1304,1307,1311,1408,1412,1488],[354,355,356,357,364],"p",{},"We host our own instance of LangFuse which you can access ",[358,359,363],"a",{"href":360,"rel":361},"https:\u002F\u002Fesplf.esprofiler.com\u002Fproject\u002Fesp-development",[362],"nofollow","here",".",[354,366,367,368,372],{},"This guide details the deployment and configuration of ",[369,370,371],"strong",{},"Langfuse"," (the open-source LLM engineering platform) on AWS ECS (Elastic Container Service).",[354,374,375],{},"To streamline the setup and avoid manual environment variable drift, we maintain a pre-configured task definition. You do not need to create a task definition from scratch; instead, you can leverage the existing definition and focus on deploying the supporting storage resources, launching the service, and wiring up DNS and Load Balancing.",[377,378,380,383,384,389],"callout",{"icon":379},"i-lucide-info",[369,381,382],{},"Latest Task Definition:"," Use the pre-configured ",[358,385,388],{"href":386,"rel":387},"https:\u002F\u002Feu-west-2.console.aws.amazon.com\u002Fecs\u002Fv2\u002Ftask-definitions\u002Fesp-langfuse?region=eu-west-2",[362],"esp-langfuse Task Definition"," on the AWS Console. This definition is already configured with container mappings for Langfuse Web, Background Workers, and database integration.",[391,392],"hr",{},[394,395,397],"h2",{"id":396},"architectural-sidecar-design","Architectural & Sidecar Design",[354,399,400,401,404],{},"To keep network overhead, latency, and costs to a minimum, Langfuse is deployed utilizing a ",[369,402,403],{},"single-task multi-container sidecar architecture",":",[406,407,412],"pre",{"className":408,"code":410,"language":411},[409],"language-text","[ ECS Task Definition: esp-langfuse ]\n┌─────────────────────────────────────────────────────────────────────────┐\n│  ┌────────────────────────────┐          ┌────────────────────────────┐ │\n│  │      esp-langfuse-web      │          │    esp-langfuse-worker     │ │\n│  │        (Port 3020)         │          │         (Sidecar)          │ │\n│  └─────────────┬──────────────┘          └─────────────┬──────────────┘ │\n│                │                                       │                │\n│                └──────────► localhost (awsvpc) ◄───────┘                │\n│                                   ▲                                     │\n│                ┌──────────────────┴──────────────────┐                  │\n│                ▼                                     ▼                  │\n│  ┌────────────────────────────┐          ┌────────────────────────────┐ │\n│  │  esp-langfuse-clickhouse   │          │     esp-langfuse-redis     │ │\n│  │         (Sidecar)          │          │         (Sidecar)          │ │\n│  └─────────────┬──────────────┘          └────────────────────────────┘ │\n│                │                                                        │\n└────────────────┼────────────────────────────────────────────────────────┘\n                 ▼\n       [ AWS EFS Volume ] (esp-langfuse-clickhouse-efs)\n","text",[413,414,410],"code",{"__ignoreMap":415},"",[417,418,419,450,471],"ul",{},[420,421,422,425,426,429,430,433,434,437,438,441,442,445,446,449],"li",{},[369,423,424],{},"Single Task Footprint:"," The core services (",[413,427,428],{},"esp-langfuse-web",", ",[413,431,432],{},"esp-langfuse-worker","), the clickhouse analytics DB (",[413,435,436],{},"esp-langfuse-clickhouse","), and the transient cache queue (",[413,439,440],{},"esp-langfuse-redis",") are bundled in the ",[369,443,444],{},"same"," task definition (",[413,447,448],{},"esp-langfuse",").",[420,451,452,455,456,459,460,463,464,467,468,449],{},[369,453,454],{},"Localhost Networking:"," Because Fargate runs these sidecars within the same ",[413,457,458],{},"awsvpc"," network namespace, the containers communicate with each other over ",[413,461,462],{},"localhost"," (e.g., Langfuse connects to Redis via ",[413,465,466],{},"localhost:6379"," and ClickHouse via ",[413,469,470],{},"http:\u002F\u002Flocalhost:8123",[420,472,473,476,477,481,482,484,485,364],{},[369,474,475],{},"ALB Target Integration:"," The Application Load Balancer (ALB) specifically routes traffic ",[478,479,480],"em",{},"only"," to the ",[413,483,428],{}," container on port ",[413,486,487],{},"3020",[391,489],{},[394,491,493],{"id":492},"part-1-storage-provisioning-s3-efs","Part 1: Storage Provisioning (S3 & EFS)",[354,495,496],{},"Langfuse requires dual storage backends: S3 for raw trace\u002FLLM payload uploads, and a persistent filesystem (EFS) for the ClickHouse container which powers high-speed analytics.",[498,499,501],"h3",{"id":500},"_1-aws-s3-bucket-setup-trace-offloading","1. AWS S3 Bucket Setup (Trace Offloading)",[503,504,505,510,516],"ol",{},[420,506,507,508,364],{},"Create a private, dedicated S3 bucket: ",[413,509,448],{},[420,511,512,515],{},[369,513,514],{},"Permissions:"," Block all public access.",[420,517,518,521,522,524],{},[369,519,520],{},"IAM Policy:"," Ensure the ECS task execution role (attached to the ",[413,523,448],{}," task definition) has read, write, and list permissions on this bucket.",[498,526,528],{"id":527},"_2-aws-efs-setup-clickhouse-persistence","2. AWS EFS Setup (ClickHouse Persistence)",[354,530,531],{},"Because AWS Fargate is serverless and stateless, any files written directly to the ClickHouse container's default filesystem will be lost upon task restarts. We mount an AWS Elastic File System (EFS) volume to ensure persistent storage of analytics data.",[503,533,534],{},[420,535,536,539,565,568],{},[369,537,538],{},"Create EFS File System:",[417,540,541,547,553,559],{},[420,542,543,544,364],{},"Go to the ",[369,545,546],{},"Amazon EFS Console",[420,548,549,550,364],{},"Click ",[369,551,552],{},"Create file system",[420,554,555,556,364],{},"Name it ",[413,557,558],{},"esp-langfuse-clickhouse-efs",[420,560,561,562,449],{},"Select our application VPC (e.g., ",[413,563,564],{},"esp-london",[566,567],"br",{},[569,570],"img",{"alt":571,"src":572},"Langfuse Task Volume Config","\u002Fimages\u002Fengineering\u002Fdeployment\u002Flangfuse-task-volume-config.png",[354,574,575],{},[478,576,577],{},"(The volume mounting configuration is fully handled by our Task Definition, but verify the following if recreating the file system):",[417,579,580,608],{},[420,581,582,585],{},[369,583,584],{},"Configure Networking (Mount Targets):",[417,586,587,594],{},[420,588,589,590,593],{},"EFS must be accessible from Fargate. Ensure that EFS ",[369,591,592],{},"Mount Targets"," are configured in the same private subnets as your ECS services.",[420,595,596,599,600,607],{},[369,597,598],{},"Security Group:"," Assign a security group to the EFS mount targets that allows inbound ",[369,601,602,603,606],{},"NFS traffic (TCP Port ",[413,604,605],{},"2049",")"," from the ECS task security group.",[420,609,610,613],{},[369,611,612],{},"Create EFS Access Point (Recommended):",[417,614,615,625,635,642],{},[420,616,617,618,621,622,364],{},"Under the created file system, navigate to the ",[369,619,620],{},"Access Points"," tab and click ",[369,623,624],{},"Create access point",[420,626,627,628,631,632,364],{},"Set ",[369,629,630],{},"Path"," to ",[413,633,634],{},"\u002Fvar\u002Flib\u002Fclickhouse",[420,636,637,638,641],{},"Set the User ID and Group ID to ",[413,639,640],{},"101"," (typical ClickHouse container user) to prevent permission collisions.",[420,643,644,645],{},"This is specified in the task definition under the ClickHouse container's mount points:\n",[406,646,650],{"className":647,"code":648,"language":649,"meta":415,"style":415},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"mountPoints\": [\n    {\n      \"sourceVolume\": \"esp-langfuse-clickhouse\",\n      \"containerPath\": \"\u002Fvar\u002Flib\u002Fclickhouse\",\n      \"readOnly\": false\n    }\n  ]\n}\n","json",[413,651,652,661,679,685,710,730,745,751,757],{"__ignoreMap":415},[653,654,657],"span",{"class":655,"line":656},"line",1,[653,658,660],{"class":659},"sMK4o","{\n",[653,662,664,667,671,674,676],{"class":655,"line":663},2,[653,665,666],{"class":659},"  \"",[653,668,670],{"class":669},"spNyl","mountPoints",[653,672,673],{"class":659},"\"",[653,675,404],{"class":659},[653,677,678],{"class":659}," [\n",[653,680,682],{"class":655,"line":681},3,[653,683,684],{"class":659},"    {\n",[653,686,688,691,695,697,699,702,705,707],{"class":655,"line":687},4,[653,689,690],{"class":659},"      \"",[653,692,694],{"class":693},"sBMFI","sourceVolume",[653,696,673],{"class":659},[653,698,404],{"class":659},[653,700,701],{"class":659}," \"",[653,703,436],{"class":704},"sfazB",[653,706,673],{"class":659},[653,708,709],{"class":659},",\n",[653,711,713,715,718,720,722,724,726,728],{"class":655,"line":712},5,[653,714,690],{"class":659},[653,716,717],{"class":693},"containerPath",[653,719,673],{"class":659},[653,721,404],{"class":659},[653,723,701],{"class":659},[653,725,634],{"class":704},[653,727,673],{"class":659},[653,729,709],{"class":659},[653,731,733,735,738,740,742],{"class":655,"line":732},6,[653,734,690],{"class":659},[653,736,737],{"class":693},"readOnly",[653,739,673],{"class":659},[653,741,404],{"class":659},[653,743,744],{"class":659}," false\n",[653,746,748],{"class":655,"line":747},7,[653,749,750],{"class":659},"    }\n",[653,752,754],{"class":655,"line":753},8,[653,755,756],{"class":659},"  ]\n",[653,758,760],{"class":655,"line":759},9,[653,761,762],{"class":659},"}\n",[391,764],{},[394,766,768],{"id":767},"part-2-ecs-service-configuration","Part 2: ECS Service Configuration",[354,770,771],{},"With storage configured, launch the service using our existing task definition.",[503,773,774,785,795],{},[420,775,776,777,780,781,784],{},"Navigate to the ",[369,778,779],{},"AWS ECS Console"," and select the ",[413,782,783],{},"esp-infrastructure"," cluster.",[420,786,787,788,791,792,364],{},"Under the ",[369,789,790],{},"Services"," tab, click ",[369,793,794],{},"Create",[420,796,797,800],{},[369,798,799],{},"Deployment Configuration:",[417,801,802,811,819,828,835],{},[420,803,804,807,808,364],{},[369,805,806],{},"Application Type:"," ",[413,809,810],{},"Service",[420,812,813,816,817,364],{},[369,814,815],{},"Family:"," Select ",[413,818,448],{},[420,820,821,824,825,449],{},[369,822,823],{},"Revision:"," Select the latest revision (referencing the ",[358,826,388],{"href":386,"rel":827},[362],[420,829,830,807,833,364],{},[369,831,832],{},"Service Name:",[413,834,448],{},[420,836,837,807,840,843,844,846],{},[369,838,839],{},"Desired Tasks:",[413,841,842],{},"1"," (Must remain at ",[413,845,842],{}," due to ClickHouse single-instance file locking over EFS).",[377,848,850,855,862,872,879,897],{"icon":849},"i-lucide-triangle-alert",[354,851,852],{},[369,853,854],{},"Critical Service Deployment Settings (Preventing EFS Lock Failures):",[354,856,857,858,861],{},"We ",[369,859,860],{},"cannot"," perform blue-green or overlapping rolling deployments for Langfuse.",[354,863,864,865,868,869,871],{},"ClickHouse relies on exclusive file-level write locks on the EFS volume. In a standard rolling deployment, AWS ECS spins up a new task container ",[478,866,867],{},"before"," stopping the old one. Because the old ",[413,870,436],{}," container is still online and actively holding the EFS lock, the new task fails to boot and acquire the file lock, causing the entire deployment to fail.",[354,873,874,875,878],{},"To resolve this issue, configure the ",[369,876,877],{},"Deployment Options"," in ECS exactly as follows:",[417,880,881,889],{},[420,882,883,807,886],{},[369,884,885],{},"Minimum healthy percent:",[413,887,888],{},"0",[420,890,891,807,894],{},[369,892,893],{},"Maximum percent:",[413,895,896],{},"100",[354,898,899,900,903],{},"This forces ECS to completely terminate the active task (releasing the ClickHouse EFS write lock) before starting up the new task. Note that this results in ",[369,901,902],{},"a few seconds of brief downtime"," during updates. We will be revisiting this storage concurrency limitation in a future release.",[503,905,906,922],{"start":687},[420,907,908,911],{},[369,909,910],{},"Volume Mounting:",[417,912,913],{},[420,914,915,916,919,920,364],{},"During the service creation wizard (or when updating the service), map the EFS volume ",[413,917,918],{},"esp-langfuse-clickhouse-data"," to the ClickHouse container path ",[413,921,634],{},[420,923,924,927],{},[369,925,926],{},"Network Configuration:",[417,928,929,935],{},[420,930,931,934],{},[369,932,933],{},"Subnets:"," Select our private subnets.",[420,936,937,939,940,943,944,971,973],{},[369,938,598],{}," Select the existing security group ",[413,941,942],{},"esp-services"," which:",[417,945,946,961],{},[420,947,948,949,951,952,954,955,364],{},"Permits inbound TCP traffic on port ",[413,950,487],{}," (",[413,953,428],{}," UI\u002FAPI) only from the ",[369,956,957,958,606],{},"AWS ALB Security Group (",[413,959,960],{},"esp-frontdoor",[420,962,963,964,967,968,970],{},"Permits outbound traffic to PostgreSQL (",[413,965,966],{},"5432","), EFS (",[413,969,605],{},"), and the public internet (for S3 and Cloudflare interaction).",[566,972],{},[569,974],{"alt":975,"src":976},"ECS task SG Langfuse","\u002Fimages\u002Fengineering\u002Fdeployment\u002Flangfuse-ecs-task-sg.png",[391,978],{},[394,980,982],{"id":981},"part-3-application-load-balancer-alb-setup","Part 3: Application Load Balancer (ALB) Setup",[354,984,985],{},"To expose Langfuse to the internet safely, configure a target group and route traffic through our existing production ALB.",[498,987,989],{"id":988},"_1-create-target-group","1. Create Target Group",[417,991,992,1001,1009,1017,1023],{},[420,993,994,807,997,1000],{},[369,995,996],{},"Target Type:",[413,998,999],{},"IP"," (Fargate tasks register by IP).",[420,1002,1003,807,1006],{},[369,1004,1005],{},"Protocol:",[413,1007,1008],{},"HTTP",[420,1010,1011,807,1014,1016],{},[369,1012,1013],{},"Port:",[413,1015,487],{}," (Targets the web container interface)",[420,1018,1019,1022],{},[369,1020,1021],{},"VPC:"," Select the application VPC.",[420,1024,1025,1028],{},[369,1026,1027],{},"Health Checks:",[417,1029,1030,1036,1049,1057,1065,1073,1081],{},[420,1031,1032,807,1034],{},[369,1033,1005],{},[413,1035,1008],{},[420,1037,1038,807,1041,1044,1045,1048],{},[369,1039,1040],{},"Path:",[413,1042,1043],{},"\u002Fapi\u002Fpublic\u002Fhealth"," (Note: This is Langfuse's default public health endpoint; do not use ",[413,1046,1047],{},"\u002F"," to avoid hitting authentication redirects).",[420,1050,1051,807,1054],{},[369,1052,1053],{},"Healthy Threshold:",[413,1055,1056],{},"2",[420,1058,1059,807,1062],{},[369,1060,1061],{},"Unhealthy Threshold:",[413,1063,1064],{},"5",[420,1066,1067,807,1070],{},[369,1068,1069],{},"Timeout:",[413,1071,1072],{},"5 seconds",[420,1074,1075,807,1078],{},[369,1076,1077],{},"Interval:",[413,1079,1080],{},"30 seconds",[420,1082,1083,807,1086],{},[369,1084,1085],{},"Success Codes:",[413,1087,1088],{},"200",[498,1090,1092],{"id":1091},"_2-configure-alb-listener-rule","2. Configure ALB Listener Rule",[354,1094,1095,1096,1099],{},"Navigate to your EC2 Application Load Balancer Listener for Port ",[413,1097,1098],{},"443"," (HTTPS).",[503,1101,1102,1108,1123,1136],{},[420,1103,1104,1105,364],{},"Add a ",[369,1106,1107],{},"New Rule",[420,1109,1110,1113],{},[369,1111,1112],{},"Conditions:",[417,1114,1115],{},[420,1116,1117,807,1120],{},[369,1118,1119],{},"Host Header:",[413,1121,1122],{},"esplf.esprofiler.com",[420,1124,1125,1128],{},[369,1126,1127],{},"Actions:",[417,1129,1130],{},[420,1131,1132,1135],{},[369,1133,1134],{},"Forward to:"," Select the Target Group created above.",[420,1137,1138,1141,1142,449],{},[369,1139,1140],{},"Priority:"," Set an appropriate rule priority index (Currently set to ",[413,1143,1088],{},[354,1145,1146],{},[569,1147],{"alt":1148,"src":1149},"ALB Rule Setup","\u002Fimages\u002Fengineering\u002Fdeployment\u002Flangfuse-alb-rule.png",[391,1151],{},[394,1153,1155],{"id":1154},"part-4-cloudflare-dns-setup","Part 4: Cloudflare DNS Setup",[354,1157,1158],{},"We manage our domain zones through Cloudflare. Map the public address to the AWS ALB.",[503,1160,1161,1168,1174,1219],{},[420,1162,1163,1164,1167],{},"Log in to the Cloudflare Dashboard and select the ",[413,1165,1166],{},"esprofiler.com"," domain zone.",[420,1169,1170,1171,364],{},"Navigate to ",[369,1172,1173],{},"DNS > Records",[420,1175,549,1176,1179,1180],{},[369,1177,1178],{},"Add Record",":\n",[417,1181,1182,1190,1201,1210],{},[420,1183,1184,807,1187],{},[369,1185,1186],{},"Type:",[413,1188,1189],{},"CNAME",[420,1191,1192,807,1195,1198,1199,606],{},[369,1193,1194],{},"Name:",[413,1196,1197],{},"esplf"," (resulting in ",[413,1200,1122],{},[420,1202,1203,1206,1207,449],{},[369,1204,1205],{},"Target:"," Enter the public DNS name of your Application Load Balancer (e.g., ",[413,1208,1209],{},"esp-prod-alb-123456789.eu-west-2.elb.amazonaws.com",[420,1211,1212,807,1215,1218],{},[369,1213,1214],{},"Proxy Status:",[413,1216,1217],{},"Proxied"," (orange cloud enabled for DDoS protection and SSL edge offloading).",[420,1220,1221],{},"Save the record.",[391,1223],{},[394,1225,1227],{"id":1226},"part-5-sso-authentication-configuration","Part 5: SSO & Authentication Configuration",[354,1229,1230],{},"In production, local credential logins should be disabled in favor of Single Sign-On (SSO). The task definition is pre-configured for Google Cloud OAuth SSO.",[354,1232,1233],{},"To complete the SSO setup:",[503,1235,1236,1246,1258,1268,1283,1290],{},[420,1237,1238,1239,1242,1243,364],{},"Register a new ",[369,1240,1241],{},"OAuth Client ID"," in the ",[369,1244,1245],{},"Google Cloud Console > APIs & Services > Credentials",[420,1247,1248,1251,1252],{},[369,1249,1250],{},"Authorized Redirect URIs:"," Configure the redirect URI pointing to:\n",[406,1253,1256],{"className":1254,"code":1255,"language":411,"meta":415},[409],"https:\u002F\u002Fesplf.esprofiler.com\u002Fapi\u002Fauth\u002Fcallback\u002Fgoogle\n",[413,1257,1255],{"__ignoreMap":415},[420,1259,1260,1261,1264,1265,364],{},"Copy the generated ",[369,1262,1263],{},"Client ID"," and ",[369,1266,1267],{},"Client Secret",[420,1269,1270,1271],{},"Securely upload them to the AWS Secrets Manager\u002FParameter Store variables injected by the task definition:\n",[417,1272,1273,1278],{},[420,1274,1275],{},[413,1276,1277],{},"AUTH_GOOGLE_CLIENT_ID",[420,1279,1280],{},[413,1281,1282],{},"AUTH_GOOGLE_CLIENT_SECRET",[420,1284,1285,1286,1289],{},"Ensure ",[413,1287,1288],{},"AUTH_DISABLE_USERNAME_PASSWORD=\"true\""," is injected into the environment to enforce SSO login.",[420,1291,1292,1293,364],{},"For more advanced settings, consult the ",[358,1294,1297],{"href":1295,"rel":1296},"https:\u002F\u002Flangfuse.com\u002Fself-hosting\u002Fsecurity\u002Fauthentication-and-sso#google",[362],"Langfuse SSO (Google) documentation",[391,1299],{},[394,1301,1303],{"id":1302},"part-6-verification-troubleshooting","Part 6: Verification & Troubleshooting",[354,1305,1306],{},"Once the service is successfully deployed, verify the installation:",[498,1308,1310],{"id":1309},"verification-steps","Verification Steps",[503,1312,1313,1319,1322,1329],{},[420,1314,1315,1316,449],{},"Navigate to your configured domain (",[413,1317,1318],{},"https:\u002F\u002Fesplf.esprofiler.com",[420,1320,1321],{},"Verify that the browser establishes a secure connection with a Cloudflare SSL certificate.",[420,1323,1324,1325,1328],{},"Select your configured ",[369,1326,1327],{},"Google SSO"," button to log in.",[420,1330,1331,1332],{},"Create a test project, generate an API key, and run a quick python script to confirm trace ingestion:\n",[406,1333,1337],{"className":1334,"code":1335,"language":1336,"meta":415,"style":415},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","from langfuse import Langfuse\n\nlangfuse = Langfuse(\n    public_key=\"pk-lf-...\",\n    secret_key=\"sk-lf-...\",\n    host=\"https:\u002F\u002Fesplf.esprofiler.com\"\n)\n\n# Ingest a mock trace\ntrace = langfuse.trace(name=\"Deployment Verification\")\ntrace.generation(name=\"Test Generation\", output=\"Success\")\nlangfuse.flush()\nprint(\"Trace uploaded successfully!\")\n","python",[413,1338,1339,1344,1350,1355,1360,1365,1370,1375,1379,1384,1390,1396,1402],{"__ignoreMap":415},[653,1340,1341],{"class":655,"line":656},[653,1342,1343],{},"from langfuse import Langfuse\n",[653,1345,1346],{"class":655,"line":663},[653,1347,1349],{"emptyLinePlaceholder":1348},true,"\n",[653,1351,1352],{"class":655,"line":681},[653,1353,1354],{},"langfuse = Langfuse(\n",[653,1356,1357],{"class":655,"line":687},[653,1358,1359],{},"    public_key=\"pk-lf-...\",\n",[653,1361,1362],{"class":655,"line":712},[653,1363,1364],{},"    secret_key=\"sk-lf-...\",\n",[653,1366,1367],{"class":655,"line":732},[653,1368,1369],{},"    host=\"https:\u002F\u002Fesplf.esprofiler.com\"\n",[653,1371,1372],{"class":655,"line":747},[653,1373,1374],{},")\n",[653,1376,1377],{"class":655,"line":753},[653,1378,1349],{"emptyLinePlaceholder":1348},[653,1380,1381],{"class":655,"line":759},[653,1382,1383],{},"# Ingest a mock trace\n",[653,1385,1387],{"class":655,"line":1386},10,[653,1388,1389],{},"trace = langfuse.trace(name=\"Deployment Verification\")\n",[653,1391,1393],{"class":655,"line":1392},11,[653,1394,1395],{},"trace.generation(name=\"Test Generation\", output=\"Success\")\n",[653,1397,1399],{"class":655,"line":1398},12,[653,1400,1401],{},"langfuse.flush()\n",[653,1403,1405],{"class":655,"line":1404},13,[653,1406,1407],{},"print(\"Trace uploaded successfully!\")\n",[498,1409,1411],{"id":1410},"troubleshooting-common-issues","Troubleshooting Common Issues",[417,1413,1414,1440,1458,1471],{},[420,1415,1416,1419],{},[369,1417,1418],{},"ALB returns 502 Bad Gateway:",[417,1420,1421,1432,1437],{},[420,1422,1423,1424,1426,1427,1429,1430,449],{},"Ensure the ECS security group (",[413,1425,942],{},") permits inbound traffic on port ",[413,1428,487],{}," from the ALB security group (",[413,1431,960],{},[420,1433,1434,1435,449],{},"Verify that the target group is hitting the correct health check path (",[413,1436,1043],{},[420,1438,1439],{},"Check the ECS task logs to see if the web container is crashing on startup.",[420,1441,1442,1445],{},[369,1443,1444],{},"EFS Mount Failures (Task Stuck in PENDING\u002FACTIVATING):",[417,1446,1447,1455],{},[420,1448,1449,1450,1452,1453,449],{},"Verify that the EFS Security Group permits inbound traffic on port ",[413,1451,605],{}," (NFS) from the ECS task security group (",[413,1454,942],{},[420,1456,1457],{},"Double-check that EFS Mount Targets are active in all subnets selected for the ECS Service.",[420,1459,1460,1463],{},[369,1461,1462],{},"Database Connection Failures:",[417,1464,1465],{},[420,1466,1467,1468,1470],{},"Ensure the RDS database Security Group has an inbound rule allowing TCP ",[413,1469,966],{}," from the ECS Task Security Group.",[420,1472,1473,1476],{},[369,1474,1475],{},"NextAuth Redirection Loop:",[417,1477,1478],{},[420,1479,1480,1481,1484,1485,1487],{},"Verify that ",[413,1482,1483],{},"NEXTAUTH_URL"," is set to the exact public HTTPS domain (",[413,1486,1318],{},") in AWS Secrets Manager \u002F Parameter Store.",[1489,1490,1491],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":415,"searchDepth":663,"depth":663,"links":1493},[1494,1495,1499,1500,1504,1505,1506],{"id":396,"depth":663,"text":397},{"id":492,"depth":663,"text":493,"children":1496},[1497,1498],{"id":500,"depth":681,"text":501},{"id":527,"depth":681,"text":528},{"id":767,"depth":663,"text":768},{"id":981,"depth":663,"text":982,"children":1501},[1502,1503],{"id":988,"depth":681,"text":989},{"id":1091,"depth":681,"text":1092},{"id":1154,"depth":663,"text":1155},{"id":1226,"depth":663,"text":1227},{"id":1302,"depth":663,"text":1303,"children":1507},[1508,1509],{"id":1309,"depth":681,"text":1310},{"id":1410,"depth":681,"text":1411},"Complete step-by-step guide for deploying and configuring Langfuse on AWS ECS using our latest task definitions, EFS for ClickHouse, S3, ALB target groups, and Cloudflare.","md",null,{},{"title":160,"description":1510},"mr66OpkvmptJAajafR_gLXlW1stEGLykg0DeaJBf-W0",[1517,1519],{"title":56,"path":157,"stem":158,"description":1518,"children":-1},"Guide on how to update the production environment for the Capability Exchange",{"title":164,"path":165,"stem":166,"description":1520,"children":-1},"Comprehensive deployment and configuration guide for the esp-platform application.yml, covering tenant-specific customization, environment profiles, database connections, central services, AI\u002FLLM observability, and ECS variables.",1789726612201]