skip to Main Content

I’m encountering a "connection already closed" error in my Django application that uses PostgreSQL as the database backend. Despite trying various solutions, I can’t seem to resolve this issue.

Background Information:

  • Django 4.2.13
  • psycopg2 2.9.9

Problem Statement

I have a Django application that intermittently throws a "connection already closed" error when trying to interact with the PostgreSQL database. This issue often arises under the following circumstances:

Running background task for inserting data into db in every 30 seconds

errors:                                                                                           File "djangoutilsasyncio.py", line 26, in innerreturn func(*args, **kwargs)
File "djangodbbackendsbasebase.py", line 330, in cursorreturn self._cursor()
File "djangodbbackendsbasebase.py", line 308, in _cursorreturn self._prepare_cursor(self.create_cursor(name))
File "djangodbutils.py", line 91, in exitraise dj_exc_value.with_traceback(traceback) from exc_value
File "djangodbbackendsbasebase.py", line 308, in _cursorreturn self._prepare_cursor(self.create_cursor(name))
File "djangoutilsasyncio.py", line 26, in innerreturn func(*args, **kwargs)
File "djangodbbackendspostgresqlbase.py", line 330, in create_cursorcursor =   
self.connection.cursor()django.db.utils.InterfaceError: connection already closed

What I’ve Tried

  • Ensured that the database connection parameters are correct.
  • Checked for any long-running queries that might be causing timeouts.
  • Adjusted Django’s database connection settings such as CONN_MAX_AGE and CONN_HEALTH_CHECKS.
  • Increased the connection timeout settings in PostgreSQL.

Despite these attempts, the issue persists.

2

Answers


  1. CONN_HEALTH_CHECKS only works in a (HTTP) request context. It doesn’t do anything when used in a background task:

    If set to True, existing persistent database connections will be health checked before they are reused in each request performing database access.

    This is a known issue.

    You should be doing a similar check manually in your loop. We don’t see your actual code, but it will be something similar to the following:

    from django.db import close_old_connections
    
    while True:
        close_old_connections()
        # ...do the things ...
        time.sleep(30) 
    
    Login or Signup to reply.
  2. If the issue is related to restarting the PostgreSQL service (reboot, apt update, etc.), you can define a dependency in your Django service file so that the Django service restarts when the PostgreSQL service is restarted. For this, you can use the BindsTo and After directives:

    [Unit]
    Description=Daphne ASGI server
    After=network.target postgresql.service
    BindsTo=postgresql.service
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search