Pixeltable: tables, transforms and HTTP routes in one app.py
The unified multimodal backend for AI data apps. Database, orchestration, and serving in one Python file.
At a glance
- What is it?
- Pixeltable puts a catalog, computed columns and FastAPI routes in a single Python application file. Here is how the mechanism works, how to install it, and where it stops being the right tool.
- Who is it for?
- Adopt Pixeltable if your pipeline is mostly Python functions over images, video, audio or documents and you want the catalog, the computed columns and the HTTP layer declared in one file. Do not adopt it if you need a database engine you can operate and query without a Python application in front of it, or if your team will not maintain app.py as the source of truth.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem Pixeltable targets: pipeline glue that nobody owns
A typical multimodal application ends up as four systems stitched together. Object storage holds the images and video. A vector database holds embeddings. An orchestrator runs the model calls. A thin service layer copies data between the three. The README frames the project as collapsing exactly that stack into one application file, and the pyproject description states the same idea in one line: declare tables, transforms, indexes and endpoints in one app.py, and inserting a row runs the transforms.
The audience is Python developers building AI data applications, not database administrators. The dependency list points the same way: numpy, pandas, pillow, av, sqlalchemy, pgvector, psycopg. Postgres with pgvector sits underneath, but the user-facing surface is Python annotations and assignments. If your team already writes pipeline code in Python and resents the copy step between stores, this is aimed at you. If your team's centre of gravity is SQL and a warehouse, it is not.
How a TableModel, a computed column and a route fit together
The README example is the clearest description of the mechanism. A class inherits from a model base and carries a name. Fields annotated with types such as pxt.Int and pxt.String are values you insert. Fields assigned an expression are computed columns: title_upper = pxtf.string.upper(title) is recomputed on insert and on update. A computed column can also call a user-defined function declared with @pxt.udf in the same file, which is how arbitrary Python, including a model call, enters the table.
Serving is declared the same way. FastAPIRouter collects routes, and add_insert_route maps a POST path to a table plus lists of input and output columns, so the response returns computed values rather than the raw row. add_compute_route maps inputs to outputs without inserting. The README notes that the port is assigned rather than fixed, and shows reading it back with pxt service list --json before issuing a request.
The separation of commands matters and is easy to get wrong. The README states plainly that pxt schema update creates the catalog and its tables but does not start HTTP, while pxt service update starts HTTP but does not create tables. Two commands, two responsibilities. The same file is meant to run unchanged against Pixeltable Cloud by targeting a URI instead of a local catalog.
Installing Pixeltable and running a first route
Installation is a pip install with the serve extra, which pulls in the HTTP serving pieces. The README then walks through initialising a local configuration, generating an example application, and pushing it to a catalog.
pip install 'pixeltable[serve]'
pxt init
pxt service example --out app.py
pxt schema update app.py my_app
pxt service update app.py my_appAfter pxt schema update the catalog my_app and its tables exist. After pxt service update HTTP is listening. The port is assigned, so read it back rather than hardcoding it, then send a row.
URL=$(pxt service list --json | jq -r '.[0].endpoint')
curl -X POST "$URL/docs" \
-H 'Content-Type: application/json' \
-d '{"doc_id": 1, "title": "Hello", "body": "world"}'The README shows the expected response for this payload: title_upper comes back as HELLO and summary as Hello. That confirms the two computed columns ran during the insert, which is the whole point of the design.
For a fuller starting point, the starter kit copies a working application. The default copy is a chat app, and the last argument selects a variant.
uvx pixeltable-new myapp
cd myapp
uv sync
pxt schema update app.py agent
pxt service update app.py agentThe README notes that inserting into the knowledge table needs no API key, but the /ask route needs ANTHROPIC_API_KEY set. If you already run FastAPI, app.include_router(...) mounts these routes on your existing application instead of starting a separate service.
Where Pixeltable is the wrong choice
The design puts a Python application in the critical path of every table definition. Tables are created by running pxt schema update against app.py, and the README is explicit that application code should use TableModel rather than pxt.create_table, which remains in notebooks and tests. That means the schema lives in code that someone must run. If your organisation expects a DBA to alter a table without a deployment, this is friction you will feel on the first urgent change.
There is a second boundary around deployment targets. The README states that pxt service run is local only and cannot target Cloud, and that pxt db update creates or updates the hosted database without inserting rows. Three commands with three distinct effects, and only one path to a hosted database. Teams that expect a single deploy command should read that sequence carefully before planning a release process.
Pixeltable Cloud itself is described in the README as being in Limited Beta, with an email address given for interest. That is a real constraint on anyone who wants a managed endpoint today. The README also does not document rollback of a schema change or of a service update, so plan migrations with that silence in mind. Finally, the README says nothing about how model calls inside computed columns are retried or rate limited; those decisions stay in your Python code.
Pixeltable versus assembling Postgres, pgvector and FastAPI yourself
The honest alternative is the stack Pixeltable sits on: Postgres with pgvector for storage and similarity search, your own Python for transforms, and FastAPI for the endpoints. Nothing in the dependency list suggests Pixeltable hides capabilities you could not build; it is a different arrangement of the same parts.
The difference is where the contract lives. In a hand-built stack, the table schema lives in migrations, the transform lives in a worker or a script, and the route lives in a service module. Three files, three review paths, and the risk that a column added to the table is not added to the endpoint. In Pixeltable the annotation, the assignment and the route are in one file, so a change to a computed column and the route that returns it move together. The README's own framing is that inserting a row runs everything below it, which is a statement about coupling: you trade separate, independently deployable services for one file that must be coherent.
That trade favours small teams and prototypes that need to become real applications, and it works against organisations that need to scale each layer independently or replace the serving layer without touching the data layer. The README's note that routes can be mounted on an existing FastAPI app with app.include_router(...) is the escape hatch for the second group: you keep your service, and take only the table and computed column layer.
Maintenance, release cadence and the Apache 2.0 licence
The repository is not archived, and its last push was on 2026-09-10. Releases are frequent: v0.7.6 on 2026-09-09, v0.7.5 on 2026-09-03, v0.7.4 on 2026-09-02. That cadence is a maintenance cost as much as a signal. On a 0.x version line with patch releases landing within a week of each other, pinning a version and reading the release notes before upgrading is the realistic posture, not tracking main.
The project is Apache-2.0, which permits commercial use and modification, and the pyproject metadata declares the same identifier. That is a permissive licence, not a legal opinion; if you redistribute Pixeltable inside a product, read the LICENSE file and your own obligations rather than this paragraph.
One upgrade cost is specific to this project and worth naming. The README warns that skill version 2.8.0 and later writes a TableModel in app.py, and that if your coding agent emits create_table in application code, the installed skill is stale and must be reinstalled. That is a real failure mode for teams using AI coding agents: the generated file looks plausible and follows the older API. The check is cheap. Look at what the agent wrote before you run pxt schema update.
What to verify before you commit to Pixeltable
Install into a virtual environment and run the five-command sequence from the README end to end. If pxt service example --out app.py produces a file whose shape you would be comfortable reviewing, the rest of the workflow will feel familiar. If the TableModel style reads as too much magic for your team, stop there.
Then test the boundary that matters most for your deployment: whether you need Cloud or local. If you need a hosted endpoint now, the Limited Beta note in the README is the first thing to resolve, because pxt service run will not get you there. If local is enough, confirm that pxt service list --json returns an endpoint your client can reach and that a POST to /docs returns the computed columns as the README shows.
Finally, decide how app.py is reviewed. The project's value comes from one file holding the schema, the transforms and the routes. That only pays off if that file is treated as the source of truth in code review, with pxt schema update and pxt service update run as deliberate steps rather than incidental ones.
Editorial conclusion
Adopt Pixeltable if your pipeline is mostly Python functions over images, video, audio or documents and you want the catalog, the computed columns and the HTTP layer declared in one file. Do not adopt it if you need a database engine you can operate and query without a Python application in front of it, or if your team will not maintain app.py as the source of truth. Before committing, verify three things on your own data: that the installed skill writes a TableModel rather than create_table, that the port from pxt service list --json is the one your client hits, and that the Cloud URI workflow (pxt db update, then pxt schema update, then pxt service update) matches how you deploy today.
Frequently asked questions
How do I install Pixeltable?
The README gives pip install 'pixeltable[serve]' as the install command, followed by pxt init to initialise the local configuration. The serve extra brings in the HTTP serving pieces used by the FastAPIRouter example.
What is the difference between pxt schema update and pxt service update?
The README states that pxt schema update creates the catalog and its tables but does not start HTTP, while pxt service update starts HTTP but does not create tables. You run both when you want tables and a listening service.
Can Pixeltable run on Pixeltable Cloud instead of locally?
Yes, the README says the same file runs on Cloud when you create an API key, set PIXELTABLE_API_KEY, name the database in pixeltable.toml and target it by URI. The sequence is pxt db update, then pxt schema update, then pxt service update against the pxt:// URI. Note that pxt service run is local only and cannot target Cloud.
Why does my coding agent still write pxt.create_table in app.py?
The README says skill version 2.8.0 and later writes a TableModel in app.py, and that an agent emitting create_table in application code means the installed skill is stale. Reinstalling the skill is the fix it gives.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pixeltable-pixeltable)