[{"data":1,"prerenderedAt":1176},["ShallowReactive",2],{"navigation_docs":3,"section-navigation-docs":130,"-docs-deployments":164,"-docs-deployments-surround":1083,"doc-previews":1088},[4,8,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126],{"title":5,"path":6,"stem":7},"Quickstart","\u002Fdocs\u002Fquickstart","docs\u002F01.quickstart",{"title":9,"path":10,"stem":11,"children":12},"Guides","\u002Fdocs\u002Fguides","docs\u002F02.guides\u002Findex",[13,14,18,22,26,30,34,38,42,46],{"title":9,"path":10,"stem":11},{"title":15,"path":16,"stem":17},"Next.js","\u002Fdocs\u002Fguides\u002Fnextjs","docs\u002F02.guides\u002F1.nextjs",{"title":19,"path":20,"stem":21},"Nuxt","\u002Fdocs\u002Fguides\u002Fnuxt","docs\u002F02.guides\u002F2.nuxt",{"title":23,"path":24,"stem":25},"SvelteKit","\u002Fdocs\u002Fguides\u002Fsveltekit","docs\u002F02.guides\u002F3.sveltekit",{"title":27,"path":28,"stem":29},"Astro","\u002Fdocs\u002Fguides\u002Fastro","docs\u002F02.guides\u002F4.astro",{"title":31,"path":32,"stem":33},"Express","\u002Fdocs\u002Fguides\u002Fexpress","docs\u002F02.guides\u002F5.express",{"title":35,"path":36,"stem":37},"FastAPI","\u002Fdocs\u002Fguides\u002Ffastapi","docs\u002F02.guides\u002F6.fastapi",{"title":39,"path":40,"stem":41},"Django","\u002Fdocs\u002Fguides\u002Fdjango","docs\u002F02.guides\u002F7.django",{"title":43,"path":44,"stem":45},"Laravel","\u002Fdocs\u002Fguides\u002Flaravel","docs\u002F02.guides\u002F8.laravel",{"title":47,"path":48,"stem":49},"Go","\u002Fdocs\u002Fguides\u002Fgo","docs\u002F02.guides\u002F9.go",{"title":51,"path":52,"stem":53},"Services","\u002Fdocs\u002Fservices","docs\u002F03.services",{"title":55,"path":56,"stem":57},"Deployments","\u002Fdocs\u002Fdeployments","docs\u002F04.deployments",{"title":59,"path":60,"stem":61},"Builds","\u002Fdocs\u002Fbuilds","docs\u002F05.builds",{"title":63,"path":64,"stem":65},"Variables","\u002Fdocs\u002Fvariables","docs\u002F06.variables",{"title":67,"path":68,"stem":69},"Domains","\u002Fdocs\u002Fdomains","docs\u002F07.domains",{"title":71,"path":72,"stem":73},"PostgreSQL","\u002Fdocs\u002Fpostgres","docs\u002F08.postgres",{"title":75,"path":76,"stem":77},"Object storage","\u002Fdocs\u002Fobject-storage","docs\u002F09.object-storage",{"title":79,"path":80,"stem":81},"Volumes","\u002Fdocs\u002Fvolumes","docs\u002F10.volumes",{"title":83,"path":84,"stem":85},"Key-value store","\u002Fdocs\u002Fredis","docs\u002F11.redis",{"title":87,"path":88,"stem":89},"Workspaces","\u002Fdocs\u002Fworkspaces","docs\u002F12.workspaces",{"title":91,"path":92,"stem":93},"Projects","\u002Fdocs\u002Fprojects","docs\u002F13.projects",{"title":95,"path":96,"stem":97},"Environments","\u002Fdocs\u002Fenvironments","docs\u002F14.environments",{"title":99,"path":100,"stem":101},"Eject","\u002Fdocs\u002Feject","docs\u002F15.eject",{"title":103,"path":104,"stem":105},"API","\u002Fdocs\u002Fapi","docs\u002F16.api",{"title":107,"path":108,"stem":109},"CLI","\u002Fdocs\u002Fcli","docs\u002F17.cli",{"title":111,"path":112,"stem":113},"Claude Plugin & MCP","\u002Fdocs\u002Fclaude-plugin","docs\u002F18.claude-plugin",{"title":115,"path":116,"stem":117},"Metrics","\u002Fdocs\u002Fmetrics","docs\u002F19.metrics",{"title":119,"path":120,"stem":121},"Logs","\u002Fdocs\u002Flogs","docs\u002F20.logs",{"title":123,"path":124,"stem":125},"Billing","\u002Fdocs\u002Fbilling","docs\u002F21.billing",{"title":127,"path":128,"stem":129},"Self-hosting","\u002Fdocs\u002Fself-hosting","docs\u002F22.self-hosting",[131,132,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163],{"title":5,"path":6,"stem":7},{"title":9,"path":10,"stem":11,"children":133},[134,135,136,137,138,139,140,141,142,143],{"title":9,"path":10,"stem":11},{"title":15,"path":16,"stem":17},{"title":19,"path":20,"stem":21},{"title":23,"path":24,"stem":25},{"title":27,"path":28,"stem":29},{"title":31,"path":32,"stem":33},{"title":35,"path":36,"stem":37},{"title":39,"path":40,"stem":41},{"title":43,"path":44,"stem":45},{"title":47,"path":48,"stem":49},{"title":51,"path":52,"stem":53},{"title":55,"path":56,"stem":57},{"title":59,"path":60,"stem":61},{"title":63,"path":64,"stem":65},{"title":67,"path":68,"stem":69},{"title":71,"path":72,"stem":73},{"title":75,"path":76,"stem":77},{"title":79,"path":80,"stem":81},{"title":83,"path":84,"stem":85},{"title":87,"path":88,"stem":89},{"title":91,"path":92,"stem":93},{"title":95,"path":96,"stem":97},{"title":99,"path":100,"stem":101},{"title":103,"path":104,"stem":105},{"title":107,"path":108,"stem":109},{"title":111,"path":112,"stem":113},{"title":115,"path":116,"stem":117},{"title":119,"path":120,"stem":121},{"title":123,"path":124,"stem":125},{"title":127,"path":128,"stem":129},{"id":165,"title":55,"body":166,"description":1077,"extension":1078,"links":1079,"meta":1080,"navigation":501,"path":56,"seo":1081,"stem":57,"__hash__":1082},"docs\u002Fdocs\u002F04.deployments.md",{"type":167,"value":168,"toc":1067},"minimark",[169,173,180,185,188,253,256,259,262,266,269,280,746,750,761,764,768,771,784,787,790,810,814,817,820,906,917,931,935,938,941,1023,1027,1034,1037,1041,1063],[170,171,172],"p",{},"A deployment is everything that happens between a commit and a running container: Lucity builds an image from your source, points the service at that image, and replaces the running instances with new ones.",[170,174,175,176,179],{},"You can watch all of it from the ",[177,178,55],"strong",{}," tab of a service, which lists every deployment with its current state and its logs.",[181,182,184],"h2",{"id":183},"deployment-steps","Deployment steps",[170,186,187],{},"Every deployment moves through the same four steps, and the dashboard shows them in order:",[189,190,191,204],"table",{},[192,193,194],"thead",{},[195,196,197,201],"tr",{},[198,199,200],"th",{},"Step",[198,202,203],{},"What happens",[205,206,207,223,233,243],"tbody",{},[195,208,209,215],{},[210,211,212],"td",{},[177,213,214],{},"Build",[210,216,217,218,222],{},"Your source is turned into a container image. See ",[219,220,221],"a",{"href":60},"builds"," for what that involves.",[195,224,225,230],{},[210,226,227],{},[177,228,229],{},"Secrets",[210,231,232],{},"The commit is scanned for leaked credentials.",[195,234,235,240],{},[210,236,237],{},[177,238,239],{},"Deploy",[210,241,242],{},"Once the build succeeds, the service is pointed at the new image.",[195,244,245,250],{},[210,246,247],{},[177,248,249],{},"Rollout",[210,251,252],{},"The new instances start and the old ones are retired.",[170,254,255],{},"Build and Secrets run at the same time. The secret scan never blocks a deployment: it reports what it found and the deploy carries on regardless. Findings are still worth acting on, because a credential that reached git history stays there until you rotate it.",[170,257,258],{},"Deploy waits for the build. If the build fails, the deploy stops and nothing changes, so the version that was already running keeps running. The same is true of every failure before the rollout starts: a broken deployment cannot take down a working service.",[170,260,261],{},"A build gets 30 minutes and is not retried. If it runs out of time, the deployment fails and you try again.",[181,263,265],{"id":264},"triggering-a-deployment","Triggering a deployment",[170,267,268],{},"There are different ways to start a deployment.",[170,270,271,272,275,276,279],{},"Each service tracks one branch, set under ",[177,273,274],{},"Settings"," → ",[177,277,278],{},"Source",". Unless you say otherwise, a deployment builds the latest commit on that branch.",[281,282,283,299,313,427,653],"tabs",{},[284,285,287,296],"tabs-item",{"label":286},"Dashboard",[170,288,289,290,292,293,295],{},"Open the service, go to the ",[177,291,55],{}," tab, and click ",[177,294,239],{},". That builds the latest commit on the tracked branch, and the dashboard offers no way to pick a different one, so change the tracked branch first if you need another.",[170,297,298],{},"Each of the four steps has its own logs, streaming while the step runs, so you can watch a build compile and a rollout come up without leaving the panel.",[284,300,302,310],{"label":301},"Git push",[170,303,304,305,275,307,309],{},"Every push to the tracked branch deploys the service. There is no workflow file and nothing to configure: this is auto-deploy, and services created in the development environment start with it switched on. You can toggle it under ",[177,306,274],{},[177,308,278],{},". Pushes to any other branch are ignored.",[170,311,312],{},"One push deploys every service that builds from that repository and tracks that branch with auto-deploy enabled, so a single commit can roll out several services at once. That is what you want when the same codebase runs as more than one service, such as a web service and a worker started with different commands.",[284,314,315,321,363,366,391,399,402,417,420],{"label":107},[170,316,317,318,320],{},"Install the CLI and sign in first: see ",[219,319,107],{"href":108}," for both.",[322,323,328],"pre",{"className":324,"code":325,"language":326,"meta":327,"style":327},"language-bash shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","lucity deploy myproject\u002Fproduction\u002Fweb --ref main --wait --timeout 30m\n","bash","",[329,330,331],"code",{"__ignoreMap":327},[332,333,336,340,344,347,351,354,357,360],"span",{"class":334,"line":335},"line",1,[332,337,339],{"class":338},"sX5TD","lucity",[332,341,343],{"class":342},"sQLXx"," deploy",[332,345,346],{"class":342}," myproject\u002Fproduction\u002Fweb",[332,348,350],{"class":349},"s1Tsi"," --ref",[332,352,353],{"class":342}," main",[332,355,356],{"class":349}," --wait",[332,358,359],{"class":349}," --timeout",[332,361,362],{"class":342}," 30m\n",[170,364,365],{},"Only the service is required. The rest are optional:",[367,368,369,376,382],"ul",{},[370,371,372,375],"li",{},[329,373,374],{},"--ref"," builds a specific commit, branch or tag instead of the tracked branch. It can be anything in the repository, not just something on the branch the service tracks.",[370,377,378,381],{},[329,379,380],{},"--wait"," blocks until the deployment is live or failed, and exits non-zero on failure, which is what makes it usable in a script. Without it the command returns as soon as the deployment has started.",[370,383,384,387,388,390],{},[329,385,386],{},"--timeout"," caps that wait. It defaults to 20 minutes and only applies with ",[329,389,380],{},".",[170,392,393,394,398],{},"See the ",[219,395,397],{"href":396},"\u002Fdocs\u002Fcli#deploy","deploy command reference"," for the full list.",[170,400,401],{},"To check the status of a service's current deployment:",[322,403,405],{"className":324,"code":404,"language":326,"meta":327,"style":327},"lucity status myproject\u002Fproduction\u002Fweb\n",[329,406,407],{"__ignoreMap":327},[332,408,409,411,414],{"class":334,"line":335},[332,410,339],{"class":338},[332,412,413],{"class":342}," status",[332,415,416],{"class":342}," myproject\u002Fproduction\u002Fweb\n",[170,418,419],{},"That exits non-zero when the rollout is failed or degraded, so a pipeline can gate on it.",[170,421,422,423,426],{},"In CI, set ",[329,424,425],{},"LUCITY_API_TOKEN"," to a workspace API token instead of signing in interactively. The CLI picks it up from the environment.",[284,428,430,442,646],{"label":429},"GitHub Actions",[170,431,432,433,436,437,275,439,441],{},"Lucity can deploy from a GitHub Actions workflow without you configuring a token anywhere, which is useful when the deploy should wait for something else first, such as a test suite. Turn on ",[177,434,435],{},"CI Deploys"," for the service under ",[177,438,274],{},[177,440,278],{},", then give the job an OIDC identity:",[322,443,447],{"className":444,"code":445,"language":446,"meta":327,"style":327},"language-yaml shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","name: Deploy\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write\n    steps:\n      - name: Install the Lucity CLI\n        env:\n          GH_TOKEN: ${{ github.token }}\n        run: |\n          gh release download --repo zeitlos\u002Flucity \\\n            --pattern 'lucity_*_linux_amd64.tar.gz' --output - | tar xz\n          sudo install lucity \u002Fusr\u002Flocal\u002Fbin\u002Flucity\n\n      - name: Deploy\n        run: lucity deploy myproject\u002Fproduction\u002Fweb --ref \"$GITHUB_SHA\" --wait\n","yaml",[329,448,449,462,471,479,496,503,511,519,530,538,549,557,571,579,590,602,608,614,620,625,636],{"__ignoreMap":327},[332,450,451,455,459],{"class":334,"line":335},[332,452,454],{"class":453},"s3drp","name",[332,456,458],{"class":457},"si-ur",":",[332,460,461],{"class":342}," Deploy\n",[332,463,465,468],{"class":334,"line":464},2,[332,466,467],{"class":349},"on",[332,469,470],{"class":457},":\n",[332,472,474,477],{"class":334,"line":473},3,[332,475,476],{"class":453},"  push",[332,478,470],{"class":457},[332,480,482,485,487,490,493],{"class":334,"line":481},4,[332,483,484],{"class":453},"    branches",[332,486,458],{"class":457},[332,488,489],{"class":457}," [",[332,491,492],{"class":342},"main",[332,494,495],{"class":457},"]\n",[332,497,499],{"class":334,"line":498},5,[332,500,502],{"emptyLinePlaceholder":501},true,"\n",[332,504,506,509],{"class":334,"line":505},6,[332,507,508],{"class":453},"jobs",[332,510,470],{"class":457},[332,512,514,517],{"class":334,"line":513},7,[332,515,516],{"class":453},"  deploy",[332,518,470],{"class":457},[332,520,522,525,527],{"class":334,"line":521},8,[332,523,524],{"class":453},"    runs-on",[332,526,458],{"class":457},[332,528,529],{"class":342}," ubuntu-latest\n",[332,531,533,536],{"class":334,"line":532},9,[332,534,535],{"class":453},"    permissions",[332,537,470],{"class":457},[332,539,541,544,546],{"class":334,"line":540},10,[332,542,543],{"class":453},"      id-token",[332,545,458],{"class":457},[332,547,548],{"class":342}," write\n",[332,550,552,555],{"class":334,"line":551},11,[332,553,554],{"class":453},"    steps",[332,556,470],{"class":457},[332,558,560,563,566,568],{"class":334,"line":559},12,[332,561,562],{"class":457},"      -",[332,564,565],{"class":453}," name",[332,567,458],{"class":457},[332,569,570],{"class":342}," Install the Lucity CLI\n",[332,572,574,577],{"class":334,"line":573},13,[332,575,576],{"class":453},"        env",[332,578,470],{"class":457},[332,580,582,585,587],{"class":334,"line":581},14,[332,583,584],{"class":453},"          GH_TOKEN",[332,586,458],{"class":457},[332,588,589],{"class":342}," ${{ github.token }}\n",[332,591,593,596,598],{"class":334,"line":592},15,[332,594,595],{"class":453},"        run",[332,597,458],{"class":457},[332,599,601],{"class":600},"sJHtc"," |\n",[332,603,605],{"class":334,"line":604},16,[332,606,607],{"class":342},"          gh release download --repo zeitlos\u002Flucity \\\n",[332,609,611],{"class":334,"line":610},17,[332,612,613],{"class":342},"            --pattern 'lucity_*_linux_amd64.tar.gz' --output - | tar xz\n",[332,615,617],{"class":334,"line":616},18,[332,618,619],{"class":342},"          sudo install lucity \u002Fusr\u002Flocal\u002Fbin\u002Flucity\n",[332,621,623],{"class":334,"line":622},19,[332,624,502],{"emptyLinePlaceholder":501},[332,626,628,630,632,634],{"class":334,"line":627},20,[332,629,562],{"class":457},[332,631,565],{"class":453},[332,633,458],{"class":457},[332,635,461],{"class":342},[332,637,639,641,643],{"class":334,"line":638},21,[332,640,595],{"class":453},[332,642,458],{"class":457},[332,644,645],{"class":342}," lucity deploy myproject\u002Fproduction\u002Fweb --ref \"$GITHUB_SHA\" --wait\n",[170,647,648,649,652],{},"The ",[329,650,651],{},"id-token: write"," permission is what makes this keyless. The CLI exchanges the job's OIDC token for a short-lived session that can only deploy services built from that same repository with CI deploys enabled.",[284,654,655,667,735],{"label":103},[170,656,657,658,661,662,666],{},"To deploy through the ",[219,659,660],{"href":104},"GraphQL API",", get an access token as described under ",[219,663,665],{"href":664},"\u002Fdocs\u002Fapi#authentication","authentication",". Deploying is then a single mutation:",[322,668,670],{"className":324,"code":669,"language":326,"meta":327,"style":327},"curl https:\u002F\u002Flucity.cloud\u002Fgraphql \\\n  -H \"Authorization: Bearer $(lucity token)\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"query\":\"mutation { deploy(service: \\\"acme\u002Fmyproject\u002Fproduction\u002Fweb\\\") { id status } }\"}'\n",[329,671,672,683,707,721],{"__ignoreMap":327},[332,673,674,677,680],{"class":334,"line":335},[332,675,676],{"class":338},"curl",[332,678,679],{"class":342}," https:\u002F\u002Flucity.cloud\u002Fgraphql",[332,681,682],{"class":349}," \\\n",[332,684,685,688,691,694,697,699,702,705],{"class":334,"line":464},[332,686,687],{"class":349},"  -H",[332,689,690],{"class":457}," \"",[332,692,693],{"class":342},"Authorization: Bearer ",[332,695,696],{"class":457},"$(",[332,698,339],{"class":338},[332,700,701],{"class":342}," token",[332,703,704],{"class":457},")\"",[332,706,682],{"class":349},[332,708,709,711,713,716,719],{"class":334,"line":473},[332,710,687],{"class":349},[332,712,690],{"class":457},[332,714,715],{"class":342},"Content-Type: application\u002Fjson",[332,717,718],{"class":457},"\"",[332,720,682],{"class":349},[332,722,723,726,729,732],{"class":334,"line":481},[332,724,725],{"class":349},"  -d",[332,727,728],{"class":457}," '",[332,730,731],{"class":342},"{\"query\":\"mutation { deploy(service: \\\"acme\u002Fmyproject\u002Fproduction\u002Fweb\\\") { id status } }\"}",[332,733,734],{"class":457},"'\n",[170,736,737,738,741,742,745],{},"The service id starts with the workspace here, because the API always takes the full id. Pass ",[329,739,740],{},"gitRef"," alongside ",[329,743,744],{},"service"," to build something other than the tracked branch.",[181,747,749],{"id":748},"configuration-changes","Configuration changes",[170,751,752,753,756,757,390],{},"Not every change needs a new image. Editing ",[219,754,755],{"href":64},"variables",", CPU and memory, the port, the start command, the health check or a volume mount reuses the image the service is already running, and applies within seconds. The new instance starts, passes its health check, and takes over before the old one goes away, so a running service does not go dark while you change it. The exception is a service with a volume attached, which ",[219,758,760],{"href":759},"\u002Fdocs\u002Fvolumes#rollout-downtime","stops before the replacement starts",[170,762,763],{},"Changing the replica count is the one change that is not a rollout at all. Existing instances keep serving and new ones simply join them.",[181,765,767],{"id":766},"rollouts","Rollouts",[170,769,770],{},"The rollout is the part where running containers are replaced, and it is arranged so that the service keeps answering throughout.",[170,772,773,774,778,779,783],{},"A new instance starts alongside the old one and receives no traffic until its ",[219,775,777],{"href":776},"\u002Fdocs\u002Fservices#health-checks","health check"," passes. Once it does, the old instance is taken out of rotation and given ten seconds to finish requests that are already in flight before it is asked to shut down. The whole shutdown has a 30 second budget, so roughly 20 seconds are left for your process to exit on its own before it is killed. That is why ",[219,780,782],{"href":781},"\u002Fdocs\u002Fservices#graceful-shutdown","handling the shutdown signal"," matters if you care about the last few requests.",[170,785,786],{},"The count never dips below what you asked for. Lucity adds an instance before removing one, rather than the other way around, so a single-replica service is covered too.",[170,788,789],{},"Two cases work differently:",[367,791,792,804],{},[370,793,794,800,801,390],{},[177,795,796,797],{},"A service with a ",[219,798,799],{"href":80},"volume"," cannot overlap, because the disk is still attached to the instance being replaced. It stops first and starts again, which means ",[219,802,803],{"href":759},"a short gap on every deploy",[370,805,806,809],{},[177,807,808],{},"A service with no port"," has nothing to health check, so a new instance counts as ready as soon as its container is up.",[181,811,813],{"id":812},"rollout-failures","Rollout failures",[170,815,816],{},"If the new instance never becomes healthy, the old one keeps serving and the deployment is marked failed. Nothing is lost and there is no rush: you can take as long as you need to work out what went wrong.",[170,818,819],{},"The deployment shows a reason, which is usually one of these:",[189,821,822,832],{},[192,823,824],{},[195,825,826,829],{},[198,827,828],{},"Reason",[198,830,831],{},"What it usually means",[205,833,834,846,854,862,870,882,890,898],{},[195,835,836,839],{},[210,837,838],{},"Crash loop",[210,840,841,842,845],{},"The container starts and exits repeatedly. The exit code is shown with it, and the ",[219,843,844],{"href":120},"logs"," have the rest.",[195,847,848,851],{},[210,849,850],{},"Out of memory",[210,852,853],{},"The container exceeded its memory limit. Raise it, or find out what is holding the memory.",[195,855,856,859],{},[210,857,858],{},"Image pull failed",[210,860,861],{},"The image could not be fetched. Most common on services built from a public image reference that no longer resolves.",[195,863,864,867],{},[210,865,866],{},"Config error",[210,868,869],{},"The container could not be created from its configuration at all.",[195,871,872,875],{},[210,873,874],{},"Quota exceeded",[210,876,877,878,390],{},"The environment ran out of its ",[219,879,881],{"href":880},"\u002Fdocs\u002Fenvironments#resource-quotas","resource budget",[195,883,884,887],{},[210,885,886],{},"Unschedulable",[210,888,889],{},"There is no capacity to place the instance right now.",[195,891,892,895],{},[210,893,894],{},"Not ready",[210,896,897],{},"The container runs fine but the health check never passes.",[195,899,900,903],{},[210,901,902],{},"Deadline exceeded",[210,904,905],{},"The rollout made no progress within the time allowed.",[170,907,908,909,912,913,916],{},"A deployment is ",[177,910,911],{},"degraded"," when some of its new instances came up and others did not, and ",[177,914,915],{},"failed"," when none of them did.",[170,918,919,920,923,924,927,928,930],{},"The service is a separate reading, and usually the one you care about. While the previous version is still serving, a service with a failed deployment shows as ",[177,921,922],{},"Degraded",": your users are fine, the new version is not. It only shows as ",[177,925,926],{},"Failed"," once nothing healthy is left, which happens on a first deployment that never worked, or on a service whose old instance had to be stopped before the new one could start, such as one with a ",[219,929,799],{"href":759}," attached.",[181,932,934],{"id":933},"rollbacks","Rollbacks",[170,936,937],{},"Reverting the change in git and pushing is always available, and with auto-deploy on it is often the first thing to reach for. That rebuilds, so it takes as long as any other deployment, but it leaves your repository and what is running in agreement.",[170,939,940],{},"When you want the previous version back without waiting for a build, Lucity can point the service straight at an image it already ran. Every deployment keeps its image, so this is live in seconds.",[281,942,943,946,958],{},[284,944,945],{"label":286},"Rolling back is not exposed in the dashboard yet. Until it is, use the Claude plugin or the API, or revert in git and let the service rebuild.",[284,947,949,955],{"label":948},"Claude plugin",[170,950,951,952,954],{},"Install the ",[219,953,948],{"href":112}," and ask for it in your own words: \"Payments have been failing in production since this morning. Find the commit that touched the payment flow and roll the api service back to whatever was deployed before it.\"",[170,956,957],{},"Run from your local checkout, the agent has your git history and the service's deployment history in front of it at the same time, so it can work out which deployment predates the change and put the service back on that image. No rebuild happens, because the image is still there.",[284,959,960,969],{"label":103},[170,961,962,963,966,967,458],{},"Call the ",[329,964,965],{},"rollback"," mutation with the id of a previous deployment, which you can read off the service in the ",[219,968,103],{"href":104},[322,970,972],{"className":324,"code":971,"language":326,"meta":327,"style":327},"curl https:\u002F\u002Flucity.cloud\u002Fgraphql \\\n  -H \"Authorization: Bearer $(lucity token)\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"query\":\"mutation { rollback(deployment: \\\"acme\u002Fmyproject\u002Fproduction\u002Fweb\u002Fbd6597fcb\\\") }\"}'\n",[329,973,974,982,1000,1012],{"__ignoreMap":327},[332,975,976,978,980],{"class":334,"line":335},[332,977,676],{"class":338},[332,979,679],{"class":342},[332,981,682],{"class":349},[332,983,984,986,988,990,992,994,996,998],{"class":334,"line":464},[332,985,687],{"class":349},[332,987,690],{"class":457},[332,989,693],{"class":342},[332,991,696],{"class":457},[332,993,339],{"class":338},[332,995,701],{"class":342},[332,997,704],{"class":457},[332,999,682],{"class":349},[332,1001,1002,1004,1006,1008,1010],{"class":334,"line":473},[332,1003,687],{"class":349},[332,1005,690],{"class":457},[332,1007,715],{"class":342},[332,1009,718],{"class":457},[332,1011,682],{"class":349},[332,1013,1014,1016,1018,1021],{"class":334,"line":481},[332,1015,725],{"class":349},[332,1017,728],{"class":457},[332,1019,1020],{"class":342},"{\"query\":\"mutation { rollback(deployment: \\\"acme\u002Fmyproject\u002Fproduction\u002Fweb\u002Fbd6597fcb\\\") }\"}",[332,1022,734],{"class":457},[181,1024,1026],{"id":1025},"one-deployment-at-a-time","One deployment at a time",[170,1028,1029,1030,1033],{},"Deployments queue rather than running all at once. At most one is active per ",[219,1031,1032],{"href":96},"environment",", so two pushes in quick succession cannot race each other into conflicting states. Queued deployments are admitted oldest first as the ones ahead of them finish.",[170,1035,1036],{},"There is also a limit on how many deployments a workspace can have waiting. Past that, a deploy is rejected with a message saying the queue is full, and you try again once something has drained.",[181,1038,1040],{"id":1039},"next-steps","Next steps",[367,1042,1043,1048,1053,1058],{},[370,1044,1045,1047],{},[219,1046,59],{"href":60}," for how a repository becomes an image",[370,1049,1050,1052],{},[219,1051,51],{"href":52}," for health checks, replicas and resources",[370,1054,1055,1057],{},[219,1056,119],{"href":120}," for what a failing container printed on its way down",[370,1059,1060,1062],{},[219,1061,95],{"href":96}," for keeping production separate from everything else",[1064,1065,1066],"style",{},"html pre.shiki code .sX5TD, html code.shiki .sX5TD{--shiki-light:#FABD2F;--shiki-default:#FABD2F;--shiki-dark:#FABD2F}html pre.shiki code .sQLXx, html code.shiki .sQLXx{--shiki-light:#B8BB26;--shiki-default:#B8BB26;--shiki-dark:#B8BB26}html pre.shiki code .s1Tsi, html code.shiki .s1Tsi{--shiki-light:#D3869B;--shiki-default:#D3869B;--shiki-dark:#D3869B}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);}html pre.shiki code .si-ur, html code.shiki .si-ur{--shiki-light:#A89984;--shiki-default:#A89984;--shiki-dark:#A89984}html pre.shiki code .s3drp, html code.shiki .s3drp{--shiki-light:#8EC07C;--shiki-default:#8EC07C;--shiki-dark:#8EC07C}html pre.shiki code .sJHtc, html code.shiki .sJHtc{--shiki-light:#FB4934;--shiki-default:#FB4934;--shiki-dark:#FB4934}",{"title":327,"searchDepth":464,"depth":464,"links":1068},[1069,1070,1071,1072,1073,1074,1075,1076],{"id":183,"depth":464,"text":184},{"id":264,"depth":464,"text":265},{"id":748,"depth":464,"text":749},{"id":766,"depth":464,"text":767},{"id":812,"depth":464,"text":813},{"id":933,"depth":464,"text":934},{"id":1025,"depth":464,"text":1026},{"id":1039,"depth":464,"text":1040},"How a deployment goes live on Lucity, and the ways to trigger one.","md",null,{},{"title":55,"description":1077},"R-IAg9ZPKPdUMbaBgCtLKd6CKrJPJscT_rVyI0wOoHE",[1084,1086],{"title":51,"path":52,"stem":53,"description":1085,"children":-1},"Services are the deployable units of a project: what they are, how they are configured, and how they scale.",{"title":59,"path":60,"stem":61,"description":1087,"children":-1},"How Lucity turns your source code into a container image.",[1089,1092,1094,1097,1100,1103,1106,1109,1112,1115,1118,1121,1124,1125,1126,1127,1129,1131,1133,1135,1137,1139,1141,1143,1145,1147,1149,1151,1153,1155,1157,1159,1161,1164,1168,1172],{"path":6,"title":1090,"description":1091},"Deploy your first service","Deploy an app to Lucity, put it on a public domain, and connect a PostgreSQL database and an object storage bucket in about fifteen minutes.",{"path":1093,"title":9,"description":1079},"\u002Fdocs\u002Fguides\u002F.navigation",{"path":16,"title":1095,"description":1096},"Deploy a Next.js app","Deploy a Next.js app on Lucity, with a database, environment variables that behave, and no Dockerfile.",{"path":20,"title":1098,"description":1099},"Deploy a Nuxt app","Deploy a Nuxt app on Lucity. Nitro output, runtime config, and a database, with no preset to pick.",{"path":24,"title":1101,"description":1102},"Deploy a SvelteKit app","Deploy a SvelteKit app on Lucity. One adapter change stands between a fresh project and a running service.",{"path":28,"title":1104,"description":1105},"Deploy an Astro site","Deploy an Astro site on Lucity, static by default and server rendered when you add an adapter.",{"path":32,"title":1107,"description":1108},"Deploy an Express API","Deploy an Express API on Lucity. Three requirements, none of them platform-specific.",{"path":36,"title":1110,"description":1111},"Deploy a FastAPI service","Deploy a FastAPI service on Lucity. Detection is picky about layout, and the fix is one setting.",{"path":40,"title":1113,"description":1114},"Deploy a Django project","Deploy a Django project on Lucity, with migrations that run themselves and static files that do not.",{"path":44,"title":1116,"description":1117},"Deploy a Laravel application","Deploy a Laravel application on Lucity, with migrations, caches and a queue worker, and no server to configure.",{"path":48,"title":1119,"description":1120},"Deploy a Go service","Deploy a Go service on Lucity. Compiled in the build, shipped as a binary, nothing else in the image.",{"path":10,"title":1122,"description":1123},"Deploy your framework","Deploy guides for the frameworks people actually ship: Next.js, Nuxt, SvelteKit, Astro, Express, FastAPI, Django, Laravel, and Go.",{"path":52,"title":51,"description":1085},{"path":56,"title":55,"description":1077},{"path":60,"title":59,"description":1087},{"path":64,"title":63,"description":1128},"Configuration for your services: service variables, shared variables, and dynamic variables.",{"path":68,"title":67,"description":1130},"Put a service on the internet. Use a platform hostname for quick tests, or a domain you own.",{"path":72,"title":71,"description":1132},"Managed PostgreSQL databases, replicated and backed up, connected to your services without copying credentials.",{"path":76,"title":75,"description":1134},"S3-compatible buckets for uploads, exports and anything else your service needs to keep.",{"path":80,"title":79,"description":1136},"Persistent disks for services that need to keep state on the filesystem.",{"path":84,"title":83,"description":1138},"A Redis®-compatible key-value store for caching, sessions and queues.",{"path":88,"title":87,"description":1140},"Workspaces represent your organization in Lucity, with their own members, isolation and billing.",{"path":92,"title":91,"description":1142},"Projects group services, databases and the environments they run in.",{"path":96,"title":95,"description":1144},"Development, staging, production: isolated copies of the same application.",{"path":100,"title":99,"description":1146},"Download a project as a Helm chart and run it on a Kubernetes cluster of your own.",{"path":104,"title":103,"description":1148},"The GraphQL API behind the dashboard, with an interactive playground.",{"path":108,"title":107,"description":1150},"Deploy and manage your services from a terminal or a CI pipeline.",{"path":112,"title":111,"description":1152},"Deploy and manage your services from Claude Code, Codex, Cursor or any other MCP client.",{"path":116,"title":115,"description":1154},"CPU and memory for every service, and disk usage for every volume.",{"path":120,"title":119,"description":1156},"What your services print while they run, and the output of every deployment step.",{"path":124,"title":123,"description":1158},"Plans, resource usage, the free trial, and what happens when a payment fails.",{"path":128,"title":127,"description":1160},"Run the whole platform on a Kubernetes cluster you own, using the same two Helm charts we run ourselves.",{"path":1162,"title":1163,"description":1079},"\u002Flegal\u002F.navigation","Legal",{"path":1165,"title":1166,"description":1167},"\u002Flegal\u002Fdata-processing-agreement","Data Processing Agreement","How Lucity processes personal data on your behalf.",{"path":1169,"title":1170,"description":1171},"\u002Flegal\u002Fprivacy-policy","Privacy Policy","How Lucity handles your data.",{"path":1173,"title":1174,"description":1175},"\u002Flegal\u002Fterms-of-use","Terms of Use","Terms governing your use of Lucity.",1791216726227]