Open-source project
pgadmin-org/pgadmin4 avatar
pgadmin-org/pgadmin4

pgAdmin 4: Building and Running the PostgreSQL Administration Platform from Source

pgAdmin is the most popular and feature rich Open Source administration and development platform for PostgreSQL, the most advanced Open Source database in the world.

3,852 stars903 forksPythonNOASSERTION

At a glance

What is it?
pgAdmin 4 is a Flask and React web application for administering PostgreSQL, deployable in a browser or as a desktop runtime. Its source build has real prerequisites, and the README documents them unevenly.
Who is it for?
Adopt pgAdmin 4 from source if you need to run it in server mode behind your own web server, or if you are packaging it for a distribution and need to control the Python and Node dependency set. Do not take this route if you only want a GUI on a laptop for an afternoon; the packaged installers and the published container image exist for that, and the README does not cover them.
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 last received commits 1 day ago.
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

What pgAdmin 4 replaces, and who ends up building it

pgAdmin 4 is a rewrite of pgAdmin3, and the README says so in its first sentence. The rewrite changed the delivery model more than the feature set: the tool is now a web application with Python and Flask on the server side and ReactJS, HTML5 and CSS on the client side. That single decision is what makes the rest of the README necessary. A traditional desktop database client ships as a binary you double-click. pgAdmin 4 ships as a Python process that serves a browser UI, and the JavaScript and CSS have to be compiled into a bundle before that process has anything to hand the browser.

The README is explicit about why the bundle exists: requesting each asset as the client needs it is less efficient than transferring one compiled bundle. That is a normal front-end build argument, and it is the reason the install instructions start with Node and yarn rather than with Python.

The audience splits in two. Most people installing pgAdmin 4 want a GUI on a workstation and will use a packaged installer or the published container image; the source tree is not aimed at them. The people the README is written for are packagers, contributors, and administrators who intend to run pgAdmin 4 in server mode on a shared host so that several DBAs reach the same PostgreSQL estate through one browser tab. If you are in that second group, the build steps below are the ones you will actually run.

The architecture: a Flask server, a compiled bundle, and an Electron shell

The data flow is worth stating plainly because it explains most of the build complexity. The Python process owns the configuration database, the connection definitions and the query execution. The browser owns rendering. Between them sits the bundle: third-party JavaScript libraries plus pgAdmin's own JavaScript, CSS and images, compiled by yarn.

The same Python server backs both deployment shapes. In server mode you point a web server or a browser at the running process. In desktop mode the runtime/ directory holds an Electron-based application that forks a Python server process and displays the UI in an embedded window. The README describes the runtime exactly that way, and the consequence is that desktop mode is not a separate codebase. It is the same server with a bundled browser around it.

One detail in the sample configuration makes the mode switch concrete. The README's example config sets SERVER_MODE and then branches on it to choose between two SQLite files, pgadmin4-desktop.db and pgadmin4-server.db, under DATA_DIR. That is a deliberate convenience for testing both modes from one checkout, and it also tells you the configuration database is SQLite by default. The same sample shows CONFIG_DATABASE_URI pointing at a PostgreSQL instance, which is how you move that state onto a real server when SQLite is not appropriate for your deployment.

Installing pgAdmin 4 from source on Linux and macOS

The README lists four prerequisites: Node.js 20 and above, yarn, Python 3.9 and above, and a PostgreSQL server. It also tells you to enable Corepack first, which puts the yarn binary on your PATH. If yarn is not already available, that step is the one people skip.

bash
corepack enable

From the top of the source tree, the README gives two make targets for the JavaScript side. The first downloads the third-party packages, and the second compiles the bundle. Both run inside web/.

bash
cd $PGADMIN4_SRC
make install-node
make bundle

On Windows, where make is not available, the README gives the equivalent commands to run from the web directory: yarn install followed by yarn run bundle. Note that the Windows path in the README does not use --immutable, while the make target does.

The Python side starts with a virtual environment, which the README recommends over the system Python. Create it, activate it, and upgrade pip, because the README states some components need a very recent pip.

bash
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip

Before installing the Python requirements, the README says to put a PostgreSQL installation's bin directory on PATH so that pg_config can be found for building psycopg3. This is the step most likely to fail on a machine that has a PostgreSQL client but not the development files.

bash
PATH=$PATH:/usr/local/pgsql/bin pip install -r $PGADMIN4_SRC/requirements.txt

The configuration file is web/config_local.py. The README says to use config.py as a reference and that any setting duplicated in config_local.py overrides config.py. A minimal development configuration from the README looks like this, and it is where you set the bind address, the port, the data directory and the mode.

python
DATA_DIR = '/Users/myuser/.pgadmin_dev'
DEFAULT_SERVER = '127.0.0.1'
DEFAULT_SERVER_PORT = 5051
SERVER_MODE = True
CONSOLE_LOG_LEVEL = logging.INFO
FILE_LOG_LEVEL = logging.INFO

The initial setup of the configuration database is interactive in server mode and non-interactive in desktop mode. You can run setup directly, or simply start pgAdmin 4 and let it run setup for you.

bash
python3 $PGADMIN4_SRC/web/setup.py
python3 $PGADMIN4_SRC/web/pgAdmin4.py

Once it starts, the README says the terminal prints the URL to open. That is the whole first-run loop: bundle, virtualenv, requirements, config_local.py, setup, browse.

Server mode against desktop mode, and the setup trap between them

The README states a limitation that deserves more attention than it gets in the install flow: running setup automatically through the runtime works in desktop mode but not in server mode, because the runtime does not allow command line interaction with the setup program. Server mode setup is interactive, so it needs a terminal or a TTY. If you are automating a server deployment, plan for that step rather than assuming the runtime will handle it.

The mode choice also changes what you are responsible for. Desktop mode gives one user a local application with a SQLite configuration database. Server mode gives multiple users a shared service, which means the configuration database, the bind address and the authentication settings all become operational concerns. The README's sample config sets MAIL_SERVER, MAIL_PORT, MAIL_USE_SSL, MAIL_USERNAME and MAIL_PASSWORD, which is the SMTP path pgAdmin uses for account mail. It does not document a rollback procedure for configuration changes, and it does not document what happens to an existing configuration database when you switch modes. The two SQLite filenames in the sample suggest the state is kept separate, but the README does not say so explicitly, and that is a gap worth closing by testing before you migrate a working server deployment.

The requirements file adds a wrinkle for long-lived deployments. Several pins are conditional on the Python version: Authlib, boto3, Flask-Security-Too and Flask-WTF all resolve to different versions above and below Python 3.9. One comment in that file explains that Flask-Security-Too 5.8.2 corrected an inverted UserMixin.is_locked() test, and that pgAdmin's User.is_locked() follows the fixed semantics, so earlier 5.8 releases would refuse all logins. A dependency pin that exists to prevent a total authentication failure is the kind of thing you want pinned on purpose, not resolved by a loose constraint.

The Docker build, and what it tells you about the toolchain

The repository ships a Dockerfile, so you do not have to reproduce the toolchain by hand if you only need a running instance. It is a multi-stage build. The first stage is an Alpine image named app-builder that installs autoconf, automake, bash, g++, git, libc6-compat, libjpeg-turbo-dev, libpng-dev, libtool, make, nasm, nodejs, npm, yarn and zlib-dev, copies web/ to /pgadmin4/web, and runs the bundle build.

Two details in that stage are worth reading before you adapt it. The build exports CPPFLAGS with -DPNG_ARM_NEON_OPT=0, which disables an ARM NEON optimization path in the image libraries. And it mounts node_modules and the generated cache as tmpfs, then deletes yarn.lock, package.json, babel.cfg, webpack configuration, jest.config.js and babel configuration after the bundle is produced. The second stage is a python:3-alpine image for the Python environment. The result is a small runtime image with no Node toolchain in it.

The Makefile exposes the same steps as targets, which is the cleaner route if you are building on a machine rather than in a container: install-node, install-python, bundle, bundle-dev, linter, check, check-audit and check-auditjs. The check target chains install-node, bundle, linter and check-pep8, then runs the JavaScript tests and the Python regression suite. The audit targets exist because the dependency tree is large; the Makefile carries a comment noting that auditjs is scoped to the dependencies group to avoid a vulnerability in the decompress package, and that the full audit is commented out pending an upstream fix. That is an honest disclosure of a known gap rather than a claim of a clean audit.

When pgAdmin 4 from source is the wrong choice

The clearest failure mode is scope. If you want a database GUI on your own machine and nothing more, building from source is the long way round. You would install Node 20, yarn, Python 3.9, a PostgreSQL server and its development headers, compile a JavaScript bundle, create a virtual environment and run an interactive setup, all to reach a UI that a packaged installer or the published container image would have given you. The README is written for people who need to control the build, not for people who need the tool.

The second case is a team that wants pgAdmin 4 in server mode but cannot give the setup program a terminal. The README states the runtime cannot interact with setup in server mode, so a fully unattended first boot is not something the documentation supports. If your deployment platform only runs containers with no interactive step, you need to solve that before you start, and the README does not tell you how.

The third case is Windows development. The README says outright that setup on Windows is somewhat more complicated and points to pkg/win32/README.md for complete details. The main README does not reproduce those steps. If your team is mixed-platform, the Windows path is a separate document you will need to read and maintain against.

A subtler mismatch is expecting pgAdmin 4 to be a monitoring or observability tool. It is an administration and development platform for PostgreSQL. It manages connections, runs queries and administers objects. Nothing in the README describes time-series metrics collection or alerting on database health, and the audit targets in the Makefile are about dependency vulnerabilities, not about your databases.

What the licence says and what it does not settle

The repository metadata reports the licence as NOASSERTION, which means the licence could not be identified from a standard SPDX identifier. The Dockerfile header resolves that ambiguity: it carries a copyright line for The pgAdmin Development Team covering 2013 to 2026 and states that the software is released under the PostgreSQL Licence. The Makefile header repeats the same statement. So the source files themselves declare the PostgreSQL Licence even though the repository's machine-readable licence field does not.

That distinction matters for anyone redistributing pgAdmin 4. The PostgreSQL Licence is a permissive licence, but you should read the LICENSE file in the repository root rather than rely on this article or on the metadata field. This is not legal advice, and the difference between what a header comment says and what a licence scanner reports is exactly the kind of thing a compliance review needs to resolve by reading the file.

Upgrade cost is dominated by the dependency pins rather than by the licence. requirements.txt carries an explicit instruction that if runtime or build time dependencies change, the committer must ensure the DEB and RPM package maintainers are informed as soon as possible. That is a maintenance commitment aimed at downstream packagers, and it tells you that version bumps in this project are coordinated events rather than private ones. If you package pgAdmin 4 for a distribution, you are inside that coordination loop. If you consume a distribution package, you are downstream of it.

Editorial conclusion

Adopt pgAdmin 4 from source if you need to run it in server mode behind your own web server, or if you are packaging it for a distribution and need to control the Python and Node dependency set. Do not take this route if you only want a GUI on a laptop for an afternoon; the packaged installers and the published container image exist for that, and the README does not cover them. Before committing, verify three things: that your PostgreSQL bin directory is on PATH so pg_config is found for psycopg3, that your Python is at least 3.9 and your Node is at least 20, and that you have read pkg/win32/README.md if any of your developers are on Windows, because the main README calls that setup more complicated and defers to that file.

Frequently asked questions

What is pgAdmin 4?

It is a rewrite of the pgAdmin3 management tool for PostgreSQL, built as a web application with Python and Flask on the server side and ReactJS, HTML5 and CSS on the client side. It can run on a web server accessed through a browser, or standalone on a workstation through an Electron-based runtime.

Is pgAdmin 4 the same as PostgreSQL?

No. PostgreSQL is the database server, and pgAdmin 4 is a separate administration and development platform that connects to it. The README lists a PostgreSQL server as a prerequisite for running pgAdmin 4.

How do I install pgAdmin 4?

From source, the README's path is to enable Corepack, run make install-node and make bundle, create a Python 3.9+ virtual environment, install requirements.txt with a PostgreSQL bin directory on PATH, edit web/config_local.py, then run web/setup.py or web/pgAdmin4.py. The README does not give install steps for packaged installers or container images.

How do I access pgAdmin 4 in a browser?

Start it with python3 $PGADMIN4_SRC/web/pgAdmin4.py, or run the setup program first. The README states that the URL to use is shown in the terminal once pgAdmin has started up.

Official sources

  1. Issues
  2. pgadmin-org/pgadmin4 on GitHub
  3. Project website
  4. README
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pgadmin-org-pgadmin4.svg)](https://hysenlabs.com/projects/pgadmin-org-pgadmin4)