Your Database Has a Web UI Problem
You spun up Postgres. You wrote your first table. Now you need to actually look at the thing without squinting at psql output in a terminal at 11 PM. Reasonable.
The usual suspects are pgAdmin, Adminer, and CloudBeaver Community. They all let you poke at databases through a browser. That’s where the similarities end.
One of them weighs 500MB and needs a team to justify it. One is a single PHP file that’ll make your security team cry. One has been the Postgres crowd’s default forever, and the UI shows it — in the way that “my dad still uses Internet Explorer” shows it. Harsh, but earned.
Here’s what actually matters when you’re picking one for your homelab or small-team setup.
The Contenders
pgAdmin 4 — The Old Reliable (That’s Slowly Getting Better)
pgAdmin is the official Postgres client. If you Googled “postgres web UI” any time in the last decade, pgAdmin was the first result, the accepted answer, and what your DBA friend told you to use.
It’s Python/Flask under the hood, ships as dpage/pgadmin4 on Docker Hub, and it does everything Postgres-related. VACUUM, ANALYZE, replication slot management, tablespace configuration, user/role administration — it’s all there. The query tool has a visual EXPLAIN plan (the one with the nodes and arrows that actually helps you understand why your query is slow). Schema diffs. Backup/restore with pg_dump integration.
Memory footprint: roughly 250MB idle. Not terrible for what it does.
The historical UI criticism is real. For years, pgAdmin felt like a Java Swing app that somehow escaped into the browser. The tree navigation, the right-click-everything workflow, the configuration panel that opens in a tab you immediately lose — none of it felt good. Version 4 has improved significantly. It’s no longer embarrassing. It’s still not pretty.
Setup complexity: Medium. You need to configure an admin email, master password, and the server connection separately. It doesn’t just “find” your Postgres instance — you tell it where to connect.
Auth: pgAdmin has its own user system. Local accounts, optionally LDAP/OAuth in the enterprise edition. The master password encrypts stored server credentials. It’s a real auth layer.
Best for: Anyone doing actual Postgres administration. Not “SELECT * FROM users” — actual DBA work. Vacuum scheduling. Index analysis. Monitoring query performance. If Postgres is your primary database and you take it seriously, pgAdmin is worth the overhead.
Adminer — The One-File Wonder
Adminer is a single PHP file. One. File. You drop it on a server, point a browser at it, enter your database credentials, and you’re in.
The Docker image (adminer on Docker Hub) is about 5MB. Memory usage is effectively zero when idle — it’s PHP, it only consumes resources when you’re actively using it. Multi-database support out of the box: Postgres, MySQL, MariaDB, SQLite, MS SQL, Oracle, and with plugins: Elasticsearch, MongoDB, ClickHouse.
The UI is… functional. It’s not winning any awards. The color scheme looks like 2008 decided to start a company. You can theme it, but even the themes feel like they were designed by someone who just discovered CSS gradients.
What it does well: it’s fast, it starts instantly, the basic operations (browse tables, run queries, dump/import) are right there without clicking through three menus. The query editor is bare-bones but it works.
Setup complexity: Almost none. Mount the file, set environment variables, done in 90 seconds.
Auth: Here’s where it gets spicy. By default, Adminer’s “auth” is just the database credentials you type on its login form. There’s no Adminer-level user management — it logs you in as whatever database user you provide. If you front it with nothing, anyone who reaches the URL gets the login form. Which they can then try to brute force with your database credentials.
There’s an ADMINER_DESIGN env var and a LoginServer plugin that restricts which servers users can connect to, but it’s not a proper access control layer.
Security reality check: Adminer is a fat target. It’s well-known, the URL pattern is predictable (/adminer.php or the container path), and a misconfigured instance with a weak postgres password is a real attack vector. You should always put it behind a reverse proxy with basic auth or IP allowlisting. Never expose it directly.
Best for: Quick “I need to check this table” sessions in a controlled environment. Local dev. One-off database inspections where you’d otherwise drop to a psql shell. Homelab use on a VPN where you’re not exposing it to the internet.
CloudBeaver Community — The Grown-Up Option
CloudBeaver is the browser-based version of DBeaver, the desktop client that half the developer world uses because it supports approximately every database that has ever existed.
The Community edition (dbeaver/cloudbeaver on Docker Hub) is free and open source. It’s Java — so the memory footprint is more substantial (~500MB idle, sometimes more depending on how many connections you have open). The startup time reflects this.
What you get for that overhead:
- Real user management. CloudBeaver has its own user/team system with RBAC. You can have a read-only analyst account and an admin account with very different capabilities.
- Multi-DB properly. Not just “it connects to multiple DBs” — it has connection management, connection templates, shared connections across users.
- Modern SQL editor. Autocomplete that actually works, query history, result export. Feels like a real IDE-adjacent tool.
- ER diagrams. View your schema visually. Useful when you inherit someone else’s database and need to figure out what they were thinking.
- Visual EXPLAIN. Similar to pgAdmin’s, works across multiple database types.
Setup complexity: Higher. CloudBeaver has its own workspace directory that needs persistent storage, and first-run setup requires going through the admin configuration wizard. It’s not complicated, but it’s more involved than Adminer.
Auth: Real RBAC. Users, roles, access control to specific connections. If you have multiple people accessing the same instance, this is the only one of the three with proper team-facing auth.
Best for: Teams. Multiple databases. Situations where you want to give a developer read access to production but not write access, and you don’t want to manage that at the database-user level for every individual.
Docker Compose Setups
pgAdmin 4
services: pgadmin: image: dpage/pgadmin4:latest container_name: pgadmin restart: unless-stopped environment: PGADMIN_DEFAULT_PASSWORD: changeme_please PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "True" ports: - "5050:80" volumes: - pgadmin_data:/var/lib/pgadmin
volumes: pgadmin_data:Connect to your Postgres instance by right-clicking “Servers” → Register → Server in the UI. The server doesn’t auto-discover.
Adminer
services: adminer: image: adminer:latest container_name: adminer restart: unless-stopped environment: ADMINER_DEFAULT_SERVER: postgres # name of your postgres service ports: - "8080:8080"If your Postgres container is on the same Docker network, use the service name as the server. If you want a specific design:
services: adminer: image: adminer:latest container_name: adminer restart: unless-stopped environment: ADMINER_DEFAULT_SERVER: postgres ADMINER_DESIGN: pepa-linha-dark ports: - "8080:8080"Available designs include pepa-linha-dark, dracula, pappu623. Yes, really.
CloudBeaver Community
services: cloudbeaver: image: dbeaver/cloudbeaver:latest container_name: cloudbeaver restart: unless-stopped ports: - "8978:8978" volumes: - cloudbeaver_workspace:/opt/cloudbeaver/workspace
volumes: cloudbeaver_workspace:First run hits a setup wizard at http://localhost:8978. Walk through it, create the admin account, configure your first connection. Workspace data persists to the named volume.
Reverse Proxy + Auth (Because You’re Not a Monster)
Adminer especially needs something in front of it if it’s reachable outside your local machine. Here’s a Caddyfile fragment for all three:
pgadmin.homelab.internal { reverse_proxy pgadmin:80}
adminer.homelab.internal { basic_auth { homelab_user $2a$14$yourhashhere } reverse_proxy adminer:8080}
cloudbeaver.homelab.internal { reverse_proxy cloudbeaver:8978}For Adminer, the basic_auth block adds HTTP basic auth on top of the database credential form. That’s a second authentication layer before anyone even sees the Adminer login page. Generate the hash with caddy hash-password.
CloudBeaver has its own login so you don’t strictly need basic auth there — just make sure the admin password isn’t admin.
pgAdmin has its own auth as well, so reverse proxy without basic auth is fine assuming it’s on a private network.
If you’re exposing any of these to the internet: don’t, but if you insist, at minimum put them behind a VPN (Tailscale, WireGuard) or use Cloudflare Access.
Feature Comparison
| Feature | pgAdmin 4 | Adminer | CloudBeaver CE |
|---|---|---|---|
| Multi-DB support | Postgres only | PG, MySQL, SQLite, MSSQL, more | PG, MySQL, MariaDB, SQLite, many more |
| Memory (idle) | ~250MB | ~30MB | ~500MB |
| Docker image size | ~400MB | ~5MB | ~700MB |
| Visual EXPLAIN | Yes | No | Yes |
| ER diagrams | Yes | No | Yes |
| Query autocomplete | Basic | No | Good |
| User/team RBAC | No (single user) | No (DB creds only) | Yes |
| Query history | Yes | No | Yes |
| Schema diff | Yes | No | Yes (limited) |
| Backup/restore UI | Yes (pg_dump) | Import/export only | Export only |
| Replication management | Yes | No | No |
| Setup time | 5–10 min | 2 min | 10–15 min |
The Honest Security Take
pgAdmin: Reasonable security story. Has its own auth, master password for credential encryption. Don’t expose port 5050 publicly. Behind a reverse proxy on a private network is fine.
Adminer: Known quantity to attackers. The /adminer path is scanned for constantly. If you’re running it: IP allowlist it, put basicauth in front of it, and ideally only spin it up when you actually need it. A compose profile can help:
services: adminer: image: adminer:latest profiles: - debug ports: - "127.0.0.1:8080:8080"Running with docker compose --profile debug up adminer means it only starts when you explicitly ask for it.
CloudBeaver: Java web app with its own user system. Keep it updated — CVEs hit Java web apps regularly. The CE edition doesn’t get the same security audit attention as the commercial version, so stay current with image tags.
Resource Reality Check
If you’re running this on a Raspberry Pi 4 or a VPS with 2GB RAM, the math changes.
Adminer is the only one with a near-zero footprint. pgAdmin at 250MB is manageable on most modern hardware. CloudBeaver at 500MB+ is fine on a NUC but will make a 1GB RAM server sweat, especially if you’re also running Postgres itself and a handful of other services.
For a typical homelab where the “database server” is also running Prometheus, Grafana, and three other containers — Adminer or pgAdmin. CloudBeaver if you’ve got the resources or the use case.
When To Use It
Use pgAdmin when:
- Postgres is your primary or only database
- You need actual DBA features: VACUUM scheduling, index analysis, replication slot management, backup integration
- You’re learning Postgres internals and want a GUI that exposes them
- You care about visual EXPLAIN plans for query tuning
Use Adminer when:
- You need to quickly inspect a table or run a one-off query
- You’re managing multiple database types (PG + MySQL + SQLite) and don’t want three different tools
- Resources are tight and 5MB matters
- You’re running it in a local dev environment where “security” is localhost
- You want something you can spin up and tear down in 30 seconds
Use CloudBeaver when:
- You have a team and need actual user management (not “tell everyone the database password”)
- You’re managing multiple database backends and want one UI with consistent UX
- You want the desktop DBeaver experience in the browser
- You’ve got the resources for a Java app and the use case to justify it
The Bottom Line
There’s no universally correct answer here, which is the honest-but-annoying take.
pgAdmin is the right tool for Postgres-specific administration. It’s not glamorous, but it does things the others don’t. If you’re serious about Postgres, you’ll want it eventually.
Adminer is the duct tape solution — and duct tape is useful. It’s what you reach for when you need to look at a table right now and you don’t want to stand up a full UI just for that. Keep a compose file for it, use it when needed, shut it down when done.
CloudBeaver is what you deploy when you’re running a proper homelab with multiple databases and multiple people. The resource overhead is real, but so is the value of not texting your friend “hey I changed the postgres password” every time you rotate credentials.
Pick based on your actual situation, not the one you wish you had. Your 2 AM “why is this query slow” self will appreciate the right choice.