Arize Phoenix's two install paths, its exact dependency pins, and the postgres password it ships in compose
AI Observability & Evaluation
At a glance
- What is it?
- Arize Phoenix is Arize's open-source AI observability and evaluation platform, written in Python and distributed as a pip package, a uvx command, and container images. Reading its manifest, compose file, and Dockerfile closely, the parts that break your setup are not the tracing features but the version ceilings, the default database credentials, and the fact that the agent endpoint shares a port with the web UI.
- Who is it for?
- Phoenix fits teams that want OpenTelemetry traces, datasets, experiments, and LLM evals on infrastructure they operate, and who are willing to own the container, the database, and the dependency surface it brings with it.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- 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 October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
pip install arize-phoenix drags in scikit-learn, scipy, and pyarrow
The runtime is not a small client library. A plain `pip install arize-phoenix` resolves scikit-learn, scipy, numpy, pandas>=1.0, pyarrow, PyYAML, jinja2, jsonpath-ng, jsonschema, pystache, psutil, uvicorn, starlette>=0.37.0, grpcio, tqdm, and httpx[http2] into the same environment as your application. The GraphQL and SQL layers come along too, through strawberry-graphql and sqlalchemy[asyncio]>=2.1.1, <3, plus alembic>=1.3.0, <2, aiosqlite, and arize-phoenix-sqlean>=0.1.2. If your service already pins pandas, numpy, or scikit-learn at a different version, pip either rewrites your pins or refuses, and that decision lands on your runtime instead of on a sidecar. Keeping Phoenix in its own container is what keeps this dependency surface from reaching the process that serves your users. The same manifest also names three sibling packages you may not expect to find bundled: arize-phoenix-evals>=3.9.0, arize-phoenix-otel>=0.17.0, and openinference-instrumentation-openai>=0.1.41, so evaluation logic and OpenInference instrumentation arrive as install-time requirements rather than something you opt into later. Python itself is bounded: requires-python reads >=3.11, <3.15, and the classifiers stop at 3.14.
The bundled compose file publishes postgres with the password postgres
docker-compose.yml wires two services. The phoenix service builds from ./Dockerfile, declares depends_on db, and maps the web and OTLP ports:
ports:
- 6006:6006
- 4317:4317
environment:
- PHOENIX_SQL_DATABASE_URL=postgresql://postgres:postgres@db:5432/postgresThe db service is `image: postgres:16` with `restart: always`, and its POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB values are all set to postgres. Port 5432 is published to the host, and a named volume database_data sits at /var/lib/postgresql/data. Those are stock image credentials written into a committed file, and the database port is exposed rather than kept on the internal network. That is fine on a laptop with a loopback interface and a liability on a shared CI runner or any machine with a routable address, where an unauthenticated postgres answers on 5432 for anyone who can reach the host. Change the password and delete the 5432 mapping before this file touches a network you do not control. Note also that this compose file is a development convenience: it builds the image from the local Dockerfile rather than pulling a tagged release, and it declares no volume for Phoenix itself, so trace and evaluation data lives wherever PHOENIX_SQL_DATABASE_URL points.
One port carries both the web UI and the agent /mcp endpoint
Three endpoints matter. The compose file and the Dockerfile comments both center on 6006, and the cursor deeplink linked from the README encodes its target as `{"url":"http://localhost:6006/mcp"}`, which puts the Remote MCP Server on the same port as the browser interface. 4317 is the OTLP gRPC receiver that trace export targets. The consequence of that arrangement is that the endpoint letting Claude Code, Cursor, and other MCP clients query traces, datasets, experiments, and more has no separate network boundary from the UI. Nothing in the setup path describes authentication on either surface, so network placement becomes the control you actually have. An agent that can reach your local UI can also reach the evaluation data behind it, and a browser tab opened on the same host can do the same.
graphql-core and sqlglot are pinned to dodge named defects
Several constraints in pyproject.toml exist because of specific bugs rather than preference:
"strawberry-graphql==0.327.7",
"graphql-core<3.3", # 3.3 changes default-value coercion used by schema searchThe graphql-core ceiling exists because 3.3 changes the default-value coercion that schema search depends on, so a careless transitive upgrade breaks a feature rather than the server. `fastapi>=0.137.0` carries a comment stating that 0.137 keeps included routers as a lazy _IncludedRouter tree and that older versions raise AssertionError on 204 routes. `opentelemetry-proto>=1.12.0` holds a floor to avoid the problem tracked in issue 2695. `sqlglot==30.18.0` is an exact pin with no range at all. You inherit a tested combination, and you also inherit ceilings chosen around Phoenix internals, so a second package in the same environment wanting a newer graphql-core forces one of you to move. openinference-semantic-conventions>=0.1.40, openinference-instrumentation>=0.1.60, and opentelemetry-sdk are held to floors in the same list, which means an upgrade of the Phoenix server can quietly raise the minimum version of your tracing libraries.
The image builds a TypeScript frontend before it touches Python
The Dockerfile is multi-stage. The frontend stage starts from node:24-slim, sets PNPM_HOME and PHOENIX_ENABLE_SOURCE_MAP=True, copies ./js and ./schemas into /phoenix, then runs `npm i -g corepack`, `corepack enable`, `corepack install`, and `pnpm install` ahead of the vite build. A comment on that stage warns that the workspace dependency @arizeai/phoenix-client regenerates its OpenAPI types from the repo-level schema while building, so the ./schemas copy has to happen or the client build fails on missing types. The usage commands are written into the file as comments:
# > docker build -t phoenix
#
# You can then run the image in the background with:
#
# > docker run -d --name phoenix -p 6006:6006 phoenix
#
# or in the foreground with:
#
# > docker run -it -p 6006:6006 phoenixThe runtime base is chosen through an ARG whose default is gcr.io/distroless/python3-debian13:nonroot, and the comment above it says to take the nonroot-arm64 variant when targeting Raspberry Pi or Apple-Silicon. Build on an arm64 host without switching that ARG and you either emulate or end up with a foreign-architecture image. The build also depends on the uv image being pinned once: a comment above it notes that both stages build on it, that it must resolve to the same digest, and that the uv version has to stay equal to the required-version recorded in pyproject.toml.
px setup only resolves if Phoenix is already installed
Trace wiring has two entry points:
npx @arizeai/phoenix-cli setup
# or, with Phoenix installed: px setupThe trailing comment is the whole difference. npx fetches the CLI at invocation time and works in a project with no Phoenix dependency at all, while px resolves only when arize-phoenix is already present. Setup detects your framework and LLM provider, installs the matching OpenInference instrumentation, and wires trace export. What it does not touch is everything else the product advertises: versioned datasets, experiments, response and retrieval evals, the playground, prompt management, and PXI all stay unconfigured until you set them up by hand after the first trace arrives. The two paths also imply two version stories, since npx resolves whatever is current at the moment you run it and px follows the pin your lockfile already holds. The framework and provider coverage is broad on paper, with entries for the OpenAI Agents SDK, Claude Agent SDK, LangGraph, Vercel AI SDK, Mastra, CrewAI, LlamaIndex, and DSPy, plus OpenAI, Anthropic, Google GenAI, Google ADK, AWS Bedrock, OpenRouter, and LiteLLM, but detection still happens through the separate OpenInference project rather than inside the CLI itself.
js/, java/, packages/, helm/, and kustomize/ share one Makefile
The repository is a monorepo carrying several deployment targets at once: Dockerfile and docker-compose.yml, helm/, kustomize/, azuredeploy.json, and app.json, alongside js/, java/, packages/, and schemas/. The Makefile is the entry point, with SHELL set to /bin/bash and .DEFAULT_GOAL set to help, driving tox, pnpm, uv, and node through targets including dev-backend, dev-frontend, dev-docker, dev-mock-llm, test-helm, doctest, codegen-python-client, codegen-ts-client, schema-ddl, check-graphql-permissions, gen-otel-models, and harbor-plugin-e2e. Contributing means standing up that toolchain rather than running pip. The distributed product stays self-hosted, with Arize AX offered as the managed option, and the note in the README states that the same OpenTelemetry and OpenInference instrumentation works with either, so traces survive a move. The Dockerfile asking how you are using Phoenix in production, and directing questions to the #phoenix-support Slack channel, is the clearest signal of who answers when it breaks. Release cadence is fast rather than cautious: arize-phoenix-v20.19.0 landed on 2026-10-01 with v20.18.0 and v20.17.0 both dated 2026-09-30, and the last push is 2026-10-02, so a version number in your lockfile can be two releases behind within a day.
Editorial conclusion
Phoenix fits teams that want OpenTelemetry traces, datasets, experiments, and LLM evals on infrastructure they operate, and who are willing to own the container, the database, and the dependency surface it brings with it. Before deploying, read the LICENSE and IP_NOTICE files yourself rather than trusting the license field, change the compose database credentials and drop the 5432 host mapping, decide whether the /mcp endpoint on port 6006 belongs on a network your agents and browsers can reach, and confirm your environment can live with the graphql-core and sqlglot ceilings the manifest pins.
Frequently asked questions
how to install phoenix
Arize Phoenix installs with `pip install arize-phoenix` followed by `phoenix serve`, or with no install at all using `uvx arize-phoenix serve`. Container images are also published to Docker Hub and deployable through the Helm chart.
Which Python versions does Arize Phoenix support?
pyproject.toml sets requires-python to >=3.11, <3.15, and the classifiers list 3.11, 3.12, 3.13, and 3.14.
What ports does the Arize Phoenix compose file expose?
The phoenix service publishes 6006:6006 and 4317:4317, and the db service publishes 5432. The database password, user, and name are all set to postgres in that file.
What license does Arize Phoenix ship under?
pyproject.toml declares license text Elastic-2.0 with LICENSE and IP_NOTICE listed as the license files, while repository metadata reports no asserted license. Read both files yourself before you choose it.
Can a coding agent query a local Arize Phoenix instance?
The Remote MCP Server exposes a /mcp endpoint, and the README cursor deeplink points at http://localhost:6006/mcp, which is the same port as the web UI.
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/arize-ai-phoenix)