# psycopg2: the libpq wrapper Python teams still run, and when to move on

> psycopg2 is a C extension that wraps libpq and implements the Python DB API 2.0. It is production-stable and still maintained, but the project itself says new features are going into Psycopg 3.

**psycopg/psycopg2** — PostgreSQL database adapter for the Python programming language

- Repository: https://github.com/psycopg/psycopg2
- Website: https://www.psycopg.org/
- Stars: 3,655 · Forks: 542
- Language: C
- License: NOASSERTION
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/psycopg-psycopg2

## What psycopg2 does that a generic database layer does not

psycopg2 is a PostgreSQL adapter for Python. It is not an ORM and it does not pretend to be database-agnostic: it speaks libpq, the client library shipped with PostgreSQL, and exposes the Python DB API 2.0 specification on top of it. That means connection objects, cursor objects, parameter binding, and the exception hierarchy defined by the DB API, all mapped onto PostgreSQL semantics.

The README names the audience directly. The library was designed for heavily multi-threaded applications that create and destroy lots of cursors and make a large number of concurrent INSERTs or UPDATEs. The thread safety claim is specific: several threads can share the same connection. That is a different guarantee from connection pooling, and it is the reason the project exists in the form it does. If your workload is one request, one connection, one cursor, you are not the target user and you will not notice the difference between this and any other driver.

The second design decision is that psycopg2 is mostly implemented in C as a libpq wrapper. The README frames this as efficiency and security: the wire protocol and type parsing happen in compiled code rather than in Python. The cost is that installing it is not a pure-Python operation, which shapes everything in the next section.

## How psycopg2 sits between your code and the server

The repository layout makes the split visible. The psycopg/ directory holds the C sources, the lib/ directory holds the Python layer, and the Makefile builds both into a package directory containing _psycopg.so alongside the pure-Python modules. The compiled extension is the part that talks to libpq; the Python modules wrap it in the DB API 2.0 interface.

Adaptation runs in both directions. The README states that many Python types are supported out of the box and adapted to matching PostgreSQL data types, and that adaptation can be extended and customized through an objects adaptation system. Practically, that is the layer you touch when you need a custom Python object to survive a round trip to a column, or when you want a specific PostgreSQL type returned as something other than the default Python type.

Beyond the basic query path, the README lists client-side and server-side cursors, asynchronous communication and notifications, and COPY TO/COPY FROM support. The cursor distinction matters more than it looks: a client-side cursor pulls the whole result into the client process, while a server-side cursor keeps the result on the server and fetches in chunks. For a large table scan, choosing the wrong one is the difference between a working job and a process killed for memory. Asynchronous communication and notification support are the features that make psycopg2 usable in event-driven code, and they are also the parts most likely to be absent from a thin driver that only implements the DB API.

## Installing psycopg2 and running a first query

The README is explicit that building Psycopg requires prerequisites: a C compiler and some development packages. It points to the install and faq documents in the doc directory, and to the online versions, for the details. If those prerequisites are met, the README gives this as the normal install path.

```bash
$ pip install psycopg2
```

If you downloaded the source package locally instead, the README shows the setup.py route, which builds the extension and then installs it. The sudo is in the README's own example.

```bash
$ python setup.py build
$ sudo python setup.py install
```

There is a third option for machines that have no compiler or no PostgreSQL development libraries. The README describes psycopg2-binary as a stand-alone package that does not require a compiler or external libraries, and gives this command. It also states plainly that the binary package is a practical choice for development and testing, but that in production it is advised to use the package built from sources. Treat that as the project's own position on the trade-off, not a formality.

```bash
$ pip install psycopg2-binary
```

For a first real use, the README does not print a connection snippet. What it does state is that the Python DB API 2.0 specification is completely implemented, so the entry point is the DB API connect call, followed by a cursor, an execute, and a commit. The repository's own test suite and the doc directory are where the project keeps its worked examples; the README itself sends readers to https://www.psycopg.org/docs/ for the API details rather than reproducing them.

What you should see after a successful connect is a cursor object you can execute against and a connection you must commit or roll back explicitly. If the import itself fails, the compiled extension did not build or was not installed, which sends you back to the prerequisites the README names. The repository also ships a Makefile target for running the test suite, which requires a test database and a user with sufficient privileges to create it; the Makefile notes that the test database setup expects the postgres user running the tests to be a superuser.

## Where psycopg2 stops fitting

The most important limitation is stated by the project, in the README, in a note: psycopg2 is still widely used and actively maintained, but it is not expected to receive new features. Psycopg 3 is described as the evolution of psycopg2 and the place where new features are being developed, with the README telling readers that if they are starting a new project they should probably start from 3. That is a maintenance posture, not an abandonment, but it changes what you can expect from a bug report asking for new capability.

The second constraint is build cost. Because psycopg2 is mostly C, every environment that installs from source needs a compiler and the PostgreSQL development packages. The psycopg2-binary wheel avoids that, at the price of the README's own advice against it for production. Teams that deploy to minimal container images or to platforms where you cannot add system packages feel this directly.

The third is the DB API 2.0 boundary itself. The API is synchronous and cursor-oriented. Asynchronous communication exists, but it is not the same thing as an async/await native interface, and code written against the DB API does not become non-blocking because the driver supports notifications. If your application is built on an async framework, the adapter's model will be visible in your code.

Finally, psycopg2 is a PostgreSQL adapter and only that. If the requirement is one code path across several database engines, psycopg2 is the wrong layer; it will not abstract anything for you, and the SQL you write will be PostgreSQL SQL.

## psycopg2 against SQLAlchemy and Psycopg 3

The two comparisons people actually make are with SQLAlchemy and with Psycopg 3, and they answer different questions.

SQLAlchemy is not a driver. It is a toolkit that sits above a driver, and psycopg2 is one of the drivers it can use underneath. Choosing SQLAlchemy means you get an ORM and a SQL expression layer, plus portability across engines; choosing psycopg2 directly means you write SQL and manage cursors yourself, with no abstraction between your code and libpq. They are not mutually exclusive, and framing it as either/or misses that the driver is still there in the SQLAlchemy stack. The real decision is whether you want an abstraction layer at all.

Psycopg 3 is the closer comparison, because it is the same project's successor. The README's own framing is that psycopg2 is not expected to receive new features while Psycopg 3 is where new features are being developed, and it recommends starting new projects on 3. The difference in approach is generational rather than architectural trivia: 3 is the line the maintainers are investing in. What psycopg2 still offers is the C libpq wrapper model, the full DB API 2.0 surface, and a long deployment history. What it does not offer is a roadmap.

## Licence, packaging and the cost of staying

The repository's LICENSE is present at the top level, but the GitHub metadata reports the licence as NOASSERTION, meaning the automated classifier could not map it to a standard identifier. The setup.py header is more informative: it states that psycopg2 is free software under the GNU Lesser General Public License, either version 3 of the License or, at your option, any later version, and it carries the usual warranty disclaimer. If licence terms matter to your organisation, read the LICENSE file and the setup.py header rather than trusting the metadata field. This is not legal advice.

Upgrade cost is where the maintenance posture has teeth. The version string in setup.py reads 2.9.13, and the packaging is plain setuptools with a pyproject.toml that requires setuptools>=70.1 and uses setuptools.build_meta as the backend. There is no exotic build system to learn. The recurring cost is elsewhere: each Python version bump and each PostgreSQL client library change has to be absorbed by a C extension, and the project has said it is not adding features. Planning a migration to Psycopg 3 is cheaper while the application is small than after years of accumulated DB API 2.0 assumptions.

The last push to the repository was on 2026-09-23. The README's note about active maintenance is consistent with a repository that is still receiving commits, but the same note sets the expectation for what those commits contain.

## Who should keep psycopg2 and who should not

Keep it if you have working code that leans on the DB API 2.0 interface, on threads sharing a connection, on server-side cursors for large result sets, or on the COPY and notification support that the README documents. Keep it if your build pipeline already compiles the extension and you have no appetite for a driver migration. Keep it if you are on SQLAlchemy and psycopg2 is the driver underneath, because that is a supported arrangement and changing it is a separate project.

Do not start there if the project is new. The README makes the recommendation itself, and starting on a library whose feature set is frozen means writing code you will migrate later. Do not pick it if you need a native async interface, if you cannot install a compiler or PostgreSQL development headers and cannot accept the binary package for production, or if you need one driver across multiple database engines.

Before adopting, verify three things: that the C compiler and PostgreSQL development packages the README lists as prerequisites are available on every host that will install the package; whether you will build from source or use psycopg2-binary, given the README's production advice; and whether the features you need are already in Psycopg 3, since the README points new projects there. The repository's own Makefile check target requires a test database and a superuser, so confirm you can reproduce that locally before trusting a build.

## Conclusion

Adopt psycopg2 for existing code that already depends on its DB API 2.0 surface, for code that needs several threads sharing one connection, and for deployments where the C extension is already compiled into the image. Do not start a greenfield project on it: the README states it is not expected to receive new features and points new projects at Psycopg 3. Before committing, verify that a C compiler and the PostgreSQL development packages are present on every build and deploy host, or decide deliberately to use psycopg2-binary and accept that the README advises building from source for production.

## FAQ

### What is psycopg2 used for?

It is a PostgreSQL database adapter for Python that implements the Python DB API 2.0 specification and wraps libpq. The README describes it as designed for heavily multi-threaded applications that create and destroy many cursors and run many concurrent INSERTs or UPDATEs.

### Which is better, psycopg or Psycopg2?

The README states that psycopg2 is still widely used and actively maintained but is not expected to receive new features, and that Psycopg 3 is the evolution of psycopg2 where new features are being developed. It adds that if you are starting a new project you should probably start from 3.

### Should I use SQLAlchemy or Psycopg2?

They are different layers rather than substitutes: SQLAlchemy is a toolkit that runs on top of a driver, and psycopg2 is one of the drivers it can use. The README describes psycopg2 only as a PostgreSQL adapter implementing the DB API 2.0, so the choice is whether you want an abstraction above the driver.

### How do I install Psycopg2?

The README gives pip install psycopg2 as the normal route once a C compiler and the development packages are present, or python setup.py build followed by sudo python setup.py install from a local source package. It also documents pip install psycopg2-binary for a stand-alone package that needs no compiler, while advising a source build for production.

## Sources

- [Issues](https://github.com/psycopg/psycopg2/issues)
- [Project website](https://www.psycopg.org/)
- [psycopg/psycopg2 on GitHub](https://github.com/psycopg/psycopg2)
- [README](https://github.com/psycopg/psycopg2/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/psycopg-psycopg2
