page:recipes:mcp server:fastapi:worker state
Host mcp server with FastAPI: worker execution and job state
Summary
Deploy a mcp server built with FastAPI as a public web service plus a dedicated worker process on Ample. ample plan --write discovers both services and their shared database and writes ample.toml; ample up reconciles the topology: a managed PostgreSQL 16 database, a public web microVM and a private worker microVM (kind worker, no public URL), both reading DATABASE_URL. Verified on FastAPI: a separately deployed worker service (kind worker, no public URL) sharing a declared managed PostgreSQL database with the web service, consuming a jobs table with row locks and marking jobs done once (worker=done attempts=1).
Representative Queries
- Host mcp server with FastAPI: worker execution and job state
- Where can I host MCP server built with FastAPI?
- I need a separately runnable worker, durable job records and idempotent retries; not a managed queue.
Prerequisites
- A repository with the web app and the worker as separate service directories (the fixture uses apps/web and apps/worker), each building and starting with the documented commands (pip install into .ample/python from requirements.txt, then uvicorn from run.py reading PORT on the python-3.12 template; the worker starts with python3 worker.py and binds no port)
- Both services read DATABASE_URL at runtime and share one jobs table; the worker claims rows with SELECT ... FOR UPDATE SKIP LOCKED and marks them done once
- An Ample account token with servers:write and databases:write (ample up creates the database)
Infrastructure Requirements
- Compute: Apps run in isolated x86_64 Firecracker microVMs that auto-pause when idle and wake on request; sizes are the priced VM sizes.
- Postgres: Managed PostgreSQL 16 runs in its own microVM and is auto-provisioned when an app needs a database and no DATABASE_URL is supplied.
Tested Configuration
- Template: python-3.12
- Runtime: python
- Size: s-1vcpu-1gb
- Install: python3 -m pip install --target .ample/python -r requirements.txt
- Start: PYTHONPATH=.ample/python:${PYTHONPATH:-} python3 run.py
Workflow Steps
Plan the topology
Run the planner once. It discovers the web and worker services, infers kind = "worker" for the process without a port, declares the database each service needs, and writes ample.toml. Exit 2 means it left questions in the manifest; answer them with --answer or by editing the file.ample plan --write .Share one database
Keep a single [databases.main] with engine = "postgres", drop any per-service database the planner added, and set DATABASE_URL = { database = "main" } under both [services.web.env] and [services.worker.env]. Python services also need an explicit start command in the manifest (the fixture sets start for both services).ample plan --offline .Apply
Reconcile the whole manifest in dependency order: the database first, then both services. It is idempotent and never destructive; exit 0 means everything applied, 2 needs input, 1 a failed resource (independent siblings still proceed and re-running resumes).ample up .Verify
Fetch the web service URL and its worker status route (/p/worker-queue/status in the example) and confirm the worker processed the enqueued job; on failure read the worker service's runtime logs.ample logs --kind runtime
Examples
- FastAPI web + worker fixture: A FastAPI web app (apps/web) and a worker process (apps/worker) sharing one managed PostgreSQL database; the queue module is under tests/deploy-canaries/_pattern-modules.
Source Reference: tests/deploy-canaries/fastapi-worker
Success Checks
- Web service responds on its public URL
http_get: Path: /, Expect: ample canary fastapi patterns - Worker consumed the enqueued job
http_get: Path: /p/worker-queue/status, Expect: worker=done attempts=1 result=processed-by-worker
Limitations
- Verified on the python-3.12 template at s-1vcpu-1gb for both services with the example fixture; other sizes, templates and FastAPI major versions are not verified.
- The mcp server itself (your job payloads, retry policy and scheduling) is application code and was not separately tested; the worker-queue check is what was verified.
- The worker is a single long-running process supervised in its own microVM; there is no scheduler, cron or horizontal worker scaling in this recipe, and the check ran immediately after deploy so idle behavior of the worker VM is not verified.
Cost Estimate
- Currency: USD
- Monthly Amount: 15.0
- Basis: size prices from pricing.toml (loaded by the API) at build revision 1ac5595375130d45290090e82ed0f554ccd45405-dirty
- Components:
- Web server: size: s-1vcpu-1gb, quantity: 1.0, monthly amount: 5.0
- Worker server: size: s-1vcpu-1gb, quantity: 1.0, monthly amount: 5.0
- Managed PostgreSQL database: size: s-1vcpu-1gb, quantity: 1.0, monthly amount: 5.0
- Note: Always-on monthly price of the tested sizes for the web service, the worker service and the database; apps auto-pause when idle.
- Components:
Evidence Summary
- Kind: canary_run
- Summary: FastAPI web service plus a separate Python worker process deployed on Ample with
ample plan --writethenample up. The web service enqueued a job that the private worker service consumed from the shared managed PostgreSQL database. - Observed At: 2026-09-20T03:56:46Z
Last Verified At
2026-09-20T03:56:46Z