All Stories
2026-10-02•9 min read

Pixeltable Cloud · Configuration · pixeltable.toml · Deployment · Secrets · API Keys · MLOps

Configure Pixeltable Cloud: pixeltable.toml, Secrets, and Deploy Order

How a Pixeltable Cloud database is configured: the pixeltable.toml entry, when the image rebuilds, the deploy order, home-bucket media, secrets, and scoped API keys.

Pierre Brunelle

Pierre Brunelle

Pixeltable Team

Summary: A Pixeltable Cloud database is one entry in pixeltable.toml. The entry names the database, chooses which project files it receives, and optionally sets the Python environment and the size it runs at. Deploy with pxt db update, then pxt schema update, then pxt service update. Provider keys are secrets. The key your app sends is a separate Pixeltable API key. This is the configuration reference for that path. The reference docs are Deploy to Pixeltable Cloud.

Pixeltable Cloud is in Limited Beta. Email [email protected] for an account, or start with pxt new, which creates a trial organization and database main. Claim it within 48 hours. The same app.py you run locally is the file you deploy. If you are declaring that file for the first time, start with How to serve a typed AI endpoint.

Two runtimes, one project#

A hosted database does two jobs, and they are not the same process.

RuntimeWhat it doesHow you start it
DatabaseHolds the catalog. Runs pxt.get_table, view iterators, and index builds. You run pxt schema update against it.pxt db update
ServiceServes the HTTP routes FastAPIRouter declares in app.py.pxt service update

Interactive HTTP does not run inside the catalog process. A code upload updates the project both of them read. An image rebuild updates the Python environment both of them run. Size the database on its [[pixeltable.database]] entry. pxt service update starts the service on the platform default.

The pixeltable.toml entry#

pxt init marks the project root. Keep the local database entry it writes, and add a hosted one. Replace myorg with the slug from pxt org list. pxt org create already provisions main.

toml

If the project already has a pyproject.toml, pxt init writes there instead. Use [[tool.pixeltable.database]] for the hosted entry. pixeltable.toml wins when both files exist.

A URI with no matching entry is an error. pxt db update pxt://myorg:main looks up the entry whose name is that URI. Leave cpu, memory_mb, disk_gb, and workers out until you have a reason to change the default.

When the default environment or size is not enough, the same entry is where those settings go:

toml
  • The default packages every file git would not ignore, including app.py at the project root. exclude drops globs from that set. include adds files an exclude or .gitignore would have dropped. It does not replace the set, so include = ["app/**"] does not mean "only the app directory," and it does not drop a root app.py. include_only is the whitelist. It cannot be combined with include or exclude. Leave include unset for the app.py this post deploys.
  • system_dependencies are conda-forge package specs, installed with micromamba when the image is built. ffmpeg is the usual one. An apt package name is not a spec.
  • python_version is 3.12 or 3.12.8. uv_options is an optional extra argument string for uv sync.
  • cpu, memory_mb, and disk_gb are the database pod. Memory has to stay between 1,024 and 4,096 MB per vCPU. A size outside that range is refused.
  • Leave workers unset. The catalog database runs as one worker. Give it more CPU and memory when schema updates, iterators, or index builds need it. Do not raise the worker count to get more HTTP throughput. That is the service.
  • disk_gb is local disk for the file cache. Rows and media are not stored on it.

pxt db diff pxt://myorg:main prints what update would change and applies nothing. Exit 0 means the database already matches the entry. Exit 2 means a change is pending. Field reference: cloud configuration.

Image rebuild or project upload#

pxt db update decides which of two artifacts changed.

What changedWhat update does
app.py, a UDF, a route, any other selected source fileUploads the project archive. Does not rebuild the image.
A dependency, python_version, or a system packageRebuilds the image. This is the slow step.
cpu, memory_mb, disk_gb, or workersResizes. The pods restart once.

The image installs packages from uv.lock or requirements.txt. With neither, pxt db update warns and the image contains Pixeltable only, which is enough for the generated example app. Anything else app.py imports belongs in one of those files. The first pxt db update builds the image and returns when the database is ready. That takes several minutes. Later code-only updates do not.

If a command reports an unsupported proxy protocol version, this Pixeltable and the database image disagree. When your local install is newer, upgrade the lockfile pin and run pxt db build-image pxt://myorg:main. pxt db restart keeps the image the pods already run. When the database is newer, run pip install -U 'pixeltable[serve]'.

Deploy order#

A new database accepts pxt db update only after pxt db status pxt://myorg:main shows AVAILABLE. From the project directory, in order, and with -f when there is no terminal to confirm in:

bash
  1. pxt db update uploads the project and applies the entry. It does not insert rows and it does not start routes.
  2. pxt schema update creates and migrates the tables. It does not start HTTP. Running it before the project is on the database fails with 404: UDF not found.
  3. pxt service update starts the hosted routes. pxt service run is local only.

pxt service list prints the URL and its routes. The host looks like https://{org}-{db}.svc.pxt.run/<service>. Copy it from the command. Do not hardcode it, and do not send service traffic to the control-plane host. Calling that service from TypeScript is How to serve a typed AI endpoint.

What to run after a change#

You changedRun
A UDF body, a route, or any .py the entry selectspxt db update, then pxt service update so running services pick up the upload
A column or a table in app.pypxt db update, then pxt schema update, then pxt service update
A dependency, the Python version, or a system packagepxt db update. The image rebuilds.
cpu, memory_mb, disk_gb, or workerspxt db update. One resize.
A secretpxt secret set, then pxt db restart and pxt service restart
Nothing, but the last build failedpxt db build-image pxt://myorg:main

Where media goes#

Every Cloud database has a home bucket at pxtfs://myorg:main/home. Hosted tables and services write there with no destination= and no destination environment variables. Inserting a local file path on a Cloud table uploads the file.

Set a destination only in two cases.

  • Local Pixeltable writing into that same bucket: sign in with pxt login or PIXELTABLE_API_KEY, then set PIXELTABLE_INPUT_MEDIA_DEST and PIXELTABLE_OUTPUT_MEDIA_DEST. See Cloud storage.
  • Your own bucket: store AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (or the GCS or Azure names) with pxt secret, and point a column at s3://, gs://, or wasbs://.
python

db_input_media_dest and db_output_media_dest on the database entry change the default for inserted or computed media. The home bucket remains the default when you set neither.

Secrets: organization, then database#

PIXELTABLE_API_KEY is how the CLI and your backend authenticate to Pixeltable Cloud. OPENAI_API_KEY and the other provider keys are secrets. They are not the same value, and provider keys do not belong in app.py.

An organization secret applies to every database. A database secret applies to that database and overrides the organization value when the names collide.

bash

A process reads its secrets once, at startup. pxt secret list prints names, never values. You can set the same keys in the Cloud dashboard.

API keys for the service#

The CLI and pxt.get_table('pxt://myorg:main/docs') work with a pxt login session. A backend that calls the hosted HTTP service needs a key. Keep it on the server. The browser calls your server.

bash

SERVICE_URL is the endpoint pxt service list printed. The example app's insert route is /docs on that URL. A key created without --grant acts as you. Cloud checks X-api-key first. A request that also sends Authorization: Bearer is authenticated as that API key.

A key with --grant is a runtime key. It belongs to the organization and reaches only its grants. Grants are a preview: Cloud refuses them until they are enabled for the organization. Until then, omit --grant.

GrantWhat that key can do
access:pxt://myorg:main/services/ingestCall the ingest service
access:pxt://myorg:main/servicesCall any service in main
access:pxt://myorg:mainThat database's services and its storage
manage:pxt://myorg:main/servicesCreate, start, stop, and delete services. It cannot read what those services return.

access and manage do not imply each other. The secret prints once. pxt key update changes grants without reissuing it. The full table is under pxt key. For a typed TypeScript client, use the walkthrough in serve a typed AI endpoint.

Operate it#

bash

stop releases compute and keeps the data. pxt db delete deletes a database and its storage. It refuses the organization's current default database. Set a different default first. A new organization's default is main.

Local and Cloud, same file#

LocalCloud
Projectpxt initthe same project, plus name = 'pxt://myorg:main'
Tablespxt schema update app.py my_apppxt schema update app.py pxt://myorg:main
HTTPpxt service update app.py my_apppxt service update app.py pxt://myorg:main
Medialocal diskpxtfs://myorg:main/home

Install with pip install -U 'pixeltable[serve]'. Sign in with pxt login for an account you already have. The commands above are the configuration. The application is still one app.py. Declaring the routes and calling them from Next.js is How to serve a typed AI endpoint.

Declarative. Multimodal. Incremental.

Focus on innovation, not infrastructure.

10-minute tutorial · Join community