[{"data":1,"prerenderedAt":997},["ShallowReactive",2],{"navigation_docs":3,"section-navigation-docs":130,"-docs-services":164,"-docs-services-surround":904,"doc-previews":909},[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":51,"body":166,"description":897,"extension":898,"links":899,"meta":900,"navigation":901,"path":52,"seo":902,"stem":53,"__hash__":903},"docs\u002Fdocs\u002F03.services.md",{"type":167,"value":168,"toc":883},"minimark",[169,178,181,184,189,192,295,302,309,316,320,324,327,330,337,373,386,399,405,419,423,430,442,453,457,473,480,522,528,532,535,546,642,645,648,651,658,662,665,674,690,697,704,707,711,718,730,733,736,739,753,760,763,776,787,795,798,801,807,811,814,824,839,843,846,853,857,879],[170,171,172,173,177],"p",{},"A service is one running program. This can be a web app, an API, a background worker, a queue consumer, or a self-hosted piece of software you didn't write. It lives in exactly one ",[174,175,176],"a",{"href":96},"environment"," and consists of its own image, its own variables, and its own compute allocation.",[170,179,180],{},"Services are the core of Lucity: everything else in a project exists to be used by services. Databases, buckets, key-value stores and volumes are all things you connect to a service.",[170,182,183],{},"Each service has a name consisting of 2 to 16 characters, lowercase letters, digits and hyphens. That name shows up in the private hostname, the generated domain, and the logs, so pick something you'll still recognize in six months. You cannot change it later.",[185,186,188],"h2",{"id":187},"source-builds-and-prebuilt-images","Source builds and prebuilt images",[170,190,191],{},"Every service is either built from a repository or pulled from a registry. You choose which one when you create the service, and that choice determines most of what follows.",[193,194,195,210],"table",{},[196,197,198],"thead",{},[199,200,201,204,207],"tr",{},[202,203],"th",{},[202,205,206],{},"From a repository",[202,208,209],{},"From an image",[211,212,213,228,239,248,264,275,286],"tbody",{},[199,214,215,219,225],{},[216,217,218],"td",{},"Where the image comes from",[216,220,221,222],{},"Lucity ",[174,223,224],{"href":60},"builds it from source",[216,226,227],{},"Pulled from a public registry",[199,229,230,233,236],{},[216,231,232],{},"Tracked branch, auto-deploy, CI deploys",[216,234,235],{},"Yes",[216,237,238],{},"No",[199,240,241,244,246],{},[216,242,243],{},"Rebuild and redeploy",[216,245,235],{},[216,247,238],{},[199,249,250,253,256],{},[216,251,252],{},"Default port",[216,254,255],{},"8080",[216,257,258,259,263],{},"Lowest TCP ",[260,261,262],"code",{},"EXPOSE"," port in the image",[199,265,266,269,272],{},[216,267,268],{},"Default start command",[216,270,271],{},"Detected by the builder",[216,273,274],{},"The image's entrypoint and command",[199,276,277,280,283],{},[216,278,279],{},"Run-as user",[216,281,282],{},"Image default",[216,284,285],{},"Configurable",[199,287,288,291,293],{},[216,289,290],{},"Vulnerability scanning",[216,292,235],{},[216,294,238],{},[170,296,297,298,301],{},"Building from a repository is the common case, and the one the ",[174,299,300],{"href":6},"quickstart"," walks through. Lucity reads the repository, works out what it is, builds a container image, and deploys it. When you push to the tracked branch, all of that happens again.",[170,303,304,305,308],{},"Deploying an image is for software you are not building yourself, such as Ghost, MySQL, Grafana, or an internal image someone else publishes. You can pick one from the Docker Hub search in the dashboard, or type any public image reference such as ",[260,306,307],{},"ghcr.io\u002Fowner\u002Fthing:1.4",".",[170,310,311,312,315],{},"Be aware that an image reference without a tag is treated as ",[260,313,314],{},"latest",", which is commonly used as a moving tag. That means the service might pull a newer image when an instance starts, if the maintainer has published one in the meantime. Lucity only pulls an image when the machine running the instance does not already have it, so this happens when an instance lands somewhere new rather than on every restart. Pin an exact version when you want to know what is running.",[317,318,319],"note",{},"The image reference is fixed when the service is created. There is no way to change the tag afterwards, so moving to a new version means adding a service on the new image and removing the old one. Images from private registries are not supported yet.",[185,321,323],{"id":322},"ports","Ports",[170,325,326],{},"A service can expose a port. If it does, the service is reachable inside its environment by default, and it can optionally also be assigned a domain. Some services, such as internal APIs, don't need a public domain at all, since their clients reach them from within the environment.",[170,328,329],{},"A service with no port configured can be the right choice for something like a worker that only reads from a queue or an external API.",[170,331,332,333,336],{},"Services built from a repository default to port ",[334,335,255],"strong",{},", and Lucity sets two variables in the container to match:",[193,338,339,349],{},[196,340,341],{},[199,342,343,346],{},[202,344,345],{},"Variable",[202,347,348],{},"Value",[211,350,351,361],{},[199,352,353,358],{},[216,354,355],{},[260,356,357],{},"PORT",[216,359,360],{},"The service port",[199,362,363,368],{},[216,364,365],{},[260,366,367],{},"HOST",[216,369,370],{},[260,371,372],{},"0.0.0.0",[170,374,375,376,378,379,382,383,385],{},"Most frameworks read ",[260,377,357],{}," without being asked, which is why a stock application usually works untouched. Binding to ",[260,380,381],{},"localhost"," instead of ",[260,384,372],{}," is the classic way to end up with a container that looks healthy while nothing can actually reach it.",[317,387,388,389,391,392,394,395,398],{},"If you define ",[260,390,357],{}," or ",[260,393,367],{}," yourself as a ",[174,396,397],{"href":64},"variable",", your value wins and Lucity stops injecting its own.",[170,400,401,402,404],{},"Services created from an image take the lowest TCP port that the image declares with ",[260,403,262],{},". Ghost lands on 2368, MySQL on 3306, and an image that exposes nothing at all gets no port.",[170,406,407,408,411,412,411,415,418],{},"You can change the port under ",[334,409,410],{},"Settings"," → ",[334,413,414],{},"Networking",[334,416,417],{},"Port",". Clearing the field turns the service into a service without a port, which removes its cluster address, its domains, and its health checks.",[185,420,422],{"id":421},"start-command","Start command",[170,424,425,426,429],{},"Services built from a repository get a start command from the builder, derived from the same signals it used to detect the framework: an npm ",[260,427,428],{},"start"," script, a Python entrypoint, or the binary it just compiled. Services created from an image use that image's entrypoint and command.",[170,431,432,433,411,435,411,438,441],{},"You can override it under ",[334,434,410],{},[334,436,437],{},"Deploy",[334,439,440],{},"Custom Start Command",". The placeholder shows the detected default, so you can always see what you are replacing.",[170,443,444,445,448,449,452],{},"The command runs through ",[260,446,447],{},"\u002Fbin\u002Fsh -c",", so shell syntax works: variable expansion, ",[260,450,451],{},"&&",", and semicolons all behave as you would expect.",[185,454,456],{"id":455},"graceful-shutdown","Graceful shutdown",[170,458,459,460,463,464,467,468,472],{},"When a ",[174,461,462],{"href":56},"deployment"," replaces an instance, the old one is asked to stop rather than killed outright. Your process receives ",[260,465,466],{},"SIGTERM"," and has ",[174,469,471],{"href":470},"\u002Fdocs\u002Fdeployments#rollouts","about twenty seconds"," to finish what it is doing and exit on its own. Ignore the signal and it is killed when the time runs out, dropping whatever was still in flight.",[170,474,475,476,479],{},"Most frameworks handle this for you. A custom start command is what usually gets in the way, since the command runs through a shell and the shell is the process that receives the signal. Prefix the real process with ",[260,477,478],{},"exec"," so that it replaces the shell:",[481,482,487],"pre",{"className":483,"code":484,"language":485,"meta":486,"style":486},"language-bash shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","npx prisma migrate deploy && exec node server.js\n","bash","",[260,488,489],{"__ignoreMap":486},[490,491,494,498,502,505,508,512,516,519],"span",{"class":492,"line":493},"line",1,[490,495,497],{"class":496},"sX5TD","npx",[490,499,501],{"class":500},"sQLXx"," prisma",[490,503,504],{"class":500}," migrate",[490,506,507],{"class":500}," deploy",[490,509,511],{"class":510},"si-ur"," &&",[490,513,515],{"class":514},"sjx4h"," exec",[490,517,518],{"class":500}," node",[490,520,521],{"class":500}," server.js\n",[170,523,524,525,527],{},"Without ",[260,526,478],{},", the shell takes the signal and your application only finds out when it is killed. With it, the application gets the full grace period.",[185,529,531],{"id":530},"health-checks","Health checks",[170,533,534],{},"By default, Lucity opens a TCP connection to the service port every 5 seconds with a 3 second timeout. An instance is considered ready after one success, and taken out of rotation after three consecutive failures. This needs no configuration and it is the right answer for most services: if the socket accepts a connection, the application is listening.",[170,536,537,538,411,540,411,542,545],{},"It is the wrong answer when your application accepts connections before it can actually serve them. An application that binds its port and then spends 40 seconds warming a cache will receive traffic it cannot answer. That is what the HTTP check is for, and you can turn it on under ",[334,539,410],{},[334,541,414],{},[334,543,544],{},"Health Check",":",[193,547,548,561],{},[196,549,550],{},[199,551,552,555,558],{},[202,553,554],{},"Field",[202,556,557],{},"Default",[202,559,560],{},"What it does",[211,562,563,577,587,598,609,620,631],{},[199,564,565,568,571],{},[216,566,567],{},"Path",[216,569,570],{},"Required",[216,572,573,574],{},"The path to request, for example ",[260,575,576],{},"\u002Fhealth\u002Fready",[199,578,579,581,584],{},[216,580,417],{},[216,582,583],{},"Service port",[216,585,586],{},"Useful when health lives on a separate admin port",[199,588,589,592,595],{},[216,590,591],{},"Delay",[216,593,594],{},"0s",[216,596,597],{},"How long to wait before the first check",[199,599,600,603,606],{},[216,601,602],{},"Period",[216,604,605],{},"5s",[216,607,608],{},"How often to check",[199,610,611,614,617],{},[216,612,613],{},"Timeout",[216,615,616],{},"3s",[216,618,619],{},"How long to wait for a response",[199,621,622,625,628],{},[216,623,624],{},"Failures",[216,626,627],{},"3",[216,629,630],{},"Consecutive failures before the instance leaves rotation",[199,632,633,636,639],{},[216,634,635],{},"Startup budget",[216,637,638],{},"0",[216,640,641],{},"Extra failures tolerated while the instance is starting",[170,643,644],{},"Any response from 200 to 399 counts as healthy.",[170,646,647],{},"The startup budget is the setting worth understanding. The steady-state values have to stay tight, because that is how a wedged instance gets pulled out of rotation quickly, but a slow boot needs the opposite. The startup budget separates the two concerns: a period of 5 seconds with a startup budget of 24 gives a new instance two minutes to come up, and as soon as it passes once, the strict steady-state rules take over.",[317,649,650],{},"Lucity uses readiness checks rather than liveness checks. A failing check takes an instance out of rotation, it does not kill the container.",[170,652,653,654,657],{},"If a new instance never passes its check, the rollout is reported as failed and the old instance keeps serving. See ",[174,655,656],{"href":56},"deployments"," for what that looks like and what to do about it.",[185,659,661],{"id":660},"cpu-and-memory","CPU and memory",[170,663,664],{},"Giving a service more CPU and memory is what is commonly called vertical scaling: the instances you already run each get more room to work in.",[170,666,667,668,411,670,673],{},"Under ",[334,669,410],{},[334,671,672],{},"Compute"," you pick a CPU and a memory size, and both apply per instance:",[675,676,677,684],"ul",{},[678,679,680,683],"li",{},[334,681,682],{},"CPU",": 0.25, 0.5, 1, 2 or 4 vCPU, defaulting to 0.5.",[678,685,686,689],{},[334,687,688],{},"Memory",": 256 MB up to 16 GB, defaulting to 512 MB.",[170,691,692,693,696],{},"Both values are limits, and the two behave differently once you hit the ceiling. Exceeding the CPU limit means your process is throttled and simply gets slower. Exceeding the memory limit means the kernel kills it, and the instance restarts with ",[260,694,695],{},"OOM killed"," recorded on the deployment. If a service dies at exactly the same point in its workload every time, that is the first thing to check.",[170,698,699,700,308],{},"Saving new values rolls the service out without a rebuild. See ",[174,701,703],{"href":702},"\u002Fdocs\u002Fdeployments#configuration-changes","configuration changes",[317,705,706],{},"Each environment has a total budget of 32 vCPU and 64 GB across everything inside it. That is plenty of room for a normal project, and a backstop against a runaway autoscaler.",[185,708,710],{"id":709},"replicas-and-autoscaling","Replicas and autoscaling",[170,712,713,714,717],{},"Running several copies of a service is what is commonly called horizontal scaling. Each replica is its own container and gets the full ",[174,715,661],{"href":716},"#cpu-and-memory"," limits you picked, so four replicas at 1 vCPU each have a vCPU to themselves.",[170,719,720,721,411,723,411,726,729],{},"A service runs between 1 and 20 instances. You can set the number yourself under ",[334,722,410],{},[334,724,725],{},"Scaling",[334,727,728],{},"Replicas",", or hand the decision to the autoscaler.",[170,731,732],{},"Adding or removing replicas does not touch the instances that are already running. Existing instances keep serving, new ones join them, and traffic spreads across whatever is ready.",[170,734,735],{},"Autoscaling watches CPU usage and adjusts the count for you. You set a minimum, a maximum, and a CPU percentage to aim for, and the autoscaler stays inside that range.",[170,737,738],{},"Scaling up reacts within about 30 seconds. Scaling down waits for 5 minutes of sustained calm and then removes at most one instance per minute, so that a short dip in traffic does not take away capacity you are about to need again.",[170,740,741,742,744,745,748,749,752],{},"Running more than one instance assumes that the service is stateless: no session state held in process memory, no uploads written to the container filesystem, and no assumption that a scheduled job runs on one particular machine. Move that state into ",[174,743,71],{"href":72},", a ",[174,746,747],{"href":84},"key-value store"," or a ",[174,750,751],{"href":76},"bucket"," before you scale out. Otherwise the requests that reach the instance holding the state work, and the rest do not.",[317,754,755,756,308],{},"This is also why a service with a mounted volume is pinned to a single replica. A volume is one disk and can only be attached to one machine at a time, so instances cannot share it. See ",[174,757,759],{"href":758},"\u002Fdocs\u002Fvolumes#one-volume-one-service","one volume, one service",[185,761,414],{"id":762},"networking",[170,764,765,766,769,770,772,773,308],{},"Every service with a port gets a private DNS name inside its environment, reachable on the same port the container listens on. From another service in the same environment the short name ",[260,767,768],{},"lucity-app-\u003Cservice>"," is enough, so a ",[174,771,397],{"href":64}," pointing one service at another can be as short as ",[260,774,775],{},"http:\u002F\u002Flucity-app-api:8080",[170,777,778,779,411,781,411,783,786],{},"The full name is shown, ready to copy, under ",[334,780,410],{},[334,782,414],{},[334,784,785],{},"Private Networking",", and it has this shape:",[481,788,793],{"className":789,"code":791,"language":792},[790],"language-text","lucity-app-\u003Cservice>.\u003Cenvironment-namespace>.svc.cluster.local\n","text",[260,794,791],{"__ignoreMap":486},[170,796,797],{},"This address is not reachable from the internet, and nothing outside the environment can reach it either. Your production database is not reachable from your staging application, in the same way that it is not reachable from someone else's workspace.",[170,799,800],{},"All services can reach the public internet, call third-party APIs, and pull from package registries.",[170,802,803,804,308],{},"To expose a service to the world, give it a domain. That is one click for a platform domain with a certificate included, or a few DNS records for a hostname you own. See ",[174,805,806],{"href":68},"domains",[185,808,810],{"id":809},"volume-mounts","Volume mounts",[170,812,813],{},"Lucity service containers are temporary. When you deploy a new version of your app, the old containers are deleted once the new one is ready. This means that files written to the filesystem are gone after a rollout.",[170,815,816,817,819,820,823],{},"Most of the time that is fine, and the answer is a ",[174,818,751],{"href":76}," for uploads and a ",[174,821,822],{"href":72},"database"," for data. Sometimes it is not, and you need a disk that outlives the container: software that insists on a data directory, a self-hosted tool with a content folder, or a database you are running yourself.",[170,825,826,827,830,831,834,835,308],{},"To get one, create a ",[174,828,829],{"href":80},"volume"," in the environment and mount it on a service at a path. Attaching a volume constrains the service in two ways: it runs as a single instance and cannot autoscale, because ",[174,832,833],{"href":758},"a disk belongs to one instance",", and every deploy stops it before starting the replacement instead of handing over cleanly, so there is a ",[174,836,838],{"href":837},"\u002Fdocs\u002Fvolumes#rollout-downtime","short gap each time",[185,840,842],{"id":841},"under-the-hood","Under the hood",[170,844,845],{},"Under the hood, each Lucity service is a Kubernetes Deployment, a Service, an optional HTTPRoute, and a Secret holding its variables, all rendered from Helm values that Lucity computes for you. Containers run with no privilege escalation, all capabilities dropped, a seccomp profile applied, and no service account token mounted.",[170,847,848,849,852],{},"There is no proprietary runtime object anywhere in that list, which is what makes ",[174,850,851],{"href":100},"ejecting"," work. You get the chart and the values, and the same service keeps running on your own infrastructure.",[185,854,856],{"id":855},"next-steps","Next steps",[675,858,859,864,869,874],{},[678,860,861,863],{},[174,862,63],{"href":64}," to configure a service and connect it to a database or bucket",[678,865,866,868],{},[174,867,55],{"href":56}," for what happens on each deploy",[678,870,871,873],{},[174,872,67],{"href":68}," to put a service on a hostname you own",[678,875,876,878],{},[174,877,115],{"href":116}," to see what a service actually uses before you resize it",[880,881,882],"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 .si-ur, html code.shiki .si-ur{--shiki-light:#A89984;--shiki-default:#A89984;--shiki-dark:#A89984}html pre.shiki code .sjx4h, html code.shiki .sjx4h{--shiki-light:#FE8019;--shiki-default:#FE8019;--shiki-dark:#FE8019}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":486,"searchDepth":884,"depth":884,"links":885},2,[886,887,888,889,890,891,892,893,894,895,896],{"id":187,"depth":884,"text":188},{"id":322,"depth":884,"text":323},{"id":421,"depth":884,"text":422},{"id":455,"depth":884,"text":456},{"id":530,"depth":884,"text":531},{"id":660,"depth":884,"text":661},{"id":709,"depth":884,"text":710},{"id":762,"depth":884,"text":414},{"id":809,"depth":884,"text":810},{"id":841,"depth":884,"text":842},{"id":855,"depth":884,"text":856},"Services are the deployable units of a project: what they are, how they are configured, and how they scale.","md",null,{},true,{"title":51,"description":897},"u_rODTTFrymE0s-MQHxEubZuNvVGZBC2g63y8pxsOSk",[905,907],{"title":47,"path":48,"stem":49,"description":906,"children":-1},"Deploy a Go service on Lucity. Compiled in the build, shipped as a binary, nothing else in the image.",{"title":55,"path":56,"stem":57,"description":908,"children":-1},"How a deployment goes live on Lucity, and the ways to trigger one.",[910,913,915,918,921,924,927,930,933,936,939,941,944,945,946,948,950,952,954,956,958,960,962,964,966,968,970,972,974,976,978,980,982,985,989,993],{"path":6,"title":911,"description":912},"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":914,"title":9,"description":899},"\u002Fdocs\u002Fguides\u002F.navigation",{"path":16,"title":916,"description":917},"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":919,"description":920},"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":922,"description":923},"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":925,"description":926},"Deploy an Astro site","Deploy an Astro site on Lucity, static by default and server rendered when you add an adapter.",{"path":32,"title":928,"description":929},"Deploy an Express API","Deploy an Express API on Lucity. Three requirements, none of them platform-specific.",{"path":36,"title":931,"description":932},"Deploy a FastAPI service","Deploy a FastAPI service on Lucity. Detection is picky about layout, and the fix is one setting.",{"path":40,"title":934,"description":935},"Deploy a Django project","Deploy a Django project on Lucity, with migrations that run themselves and static files that do not.",{"path":44,"title":937,"description":938},"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":940,"description":906},"Deploy a Go service",{"path":10,"title":942,"description":943},"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":897},{"path":56,"title":55,"description":908},{"path":60,"title":59,"description":947},"How Lucity turns your source code into a container image.",{"path":64,"title":63,"description":949},"Configuration for your services: service variables, shared variables, and dynamic variables.",{"path":68,"title":67,"description":951},"Put a service on the internet. Use a platform hostname for quick tests, or a domain you own.",{"path":72,"title":71,"description":953},"Managed PostgreSQL databases, replicated and backed up, connected to your services without copying credentials.",{"path":76,"title":75,"description":955},"S3-compatible buckets for uploads, exports and anything else your service needs to keep.",{"path":80,"title":79,"description":957},"Persistent disks for services that need to keep state on the filesystem.",{"path":84,"title":83,"description":959},"A Redis®-compatible key-value store for caching, sessions and queues.",{"path":88,"title":87,"description":961},"Workspaces represent your organization in Lucity, with their own members, isolation and billing.",{"path":92,"title":91,"description":963},"Projects group services, databases and the environments they run in.",{"path":96,"title":95,"description":965},"Development, staging, production: isolated copies of the same application.",{"path":100,"title":99,"description":967},"Download a project as a Helm chart and run it on a Kubernetes cluster of your own.",{"path":104,"title":103,"description":969},"The GraphQL API behind the dashboard, with an interactive playground.",{"path":108,"title":107,"description":971},"Deploy and manage your services from a terminal or a CI pipeline.",{"path":112,"title":111,"description":973},"Deploy and manage your services from Claude Code, Codex, Cursor or any other MCP client.",{"path":116,"title":115,"description":975},"CPU and memory for every service, and disk usage for every volume.",{"path":120,"title":119,"description":977},"What your services print while they run, and the output of every deployment step.",{"path":124,"title":123,"description":979},"Plans, resource usage, the free trial, and what happens when a payment fails.",{"path":128,"title":127,"description":981},"Run the whole platform on a Kubernetes cluster you own, using the same two Helm charts we run ourselves.",{"path":983,"title":984,"description":899},"\u002Flegal\u002F.navigation","Legal",{"path":986,"title":987,"description":988},"\u002Flegal\u002Fdata-processing-agreement","Data Processing Agreement","How Lucity processes personal data on your behalf.",{"path":990,"title":991,"description":992},"\u002Flegal\u002Fprivacy-policy","Privacy Policy","How Lucity handles your data.",{"path":994,"title":995,"description":996},"\u002Flegal\u002Fterms-of-use","Terms of Use","Terms governing your use of Lucity.",1791216727951]