Refreshing an OAuth2 access token safely with select_for_update

Backend Live Coding November 13, 2026 python

I store the token and its expiry encrypted in the database.

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# ======================================================================
# Q: How do you refresh an OAuth2 access token without 50 workers doing it at
# the same time?
#
# I store the token and its expiry encrypted in the database. I refresh shortly
# before it expires. To avoid a double refresh (some providers invalidate the
# old refresh token), I lock the row with select_for_update and re-check inside
# the lock.
# If the refresh fails with invalid_grant (the user revoked access), I mark the
# integration as disconnected and notify the customer, instead of retrying
# forever.
# ======================================================================

def get_access_token(integration_id):
    integ = Integration.objects.get(pk=integration_id)
    if integ.expires_at > now() + timedelta(minutes=2):
        return integ.access_token                  # fast path
    with transaction.atomic():
        integ = Integration.objects.select_for_update().get(pk=integration_id)
        if integ.expires_at > now() + timedelta(minutes=2):
            return integ.access_token              # another worker already refreshed it
        tokens = oauth_provider.refresh(integ.refresh_token)
        integ.access_token = tokens['access_token']
        integ.refresh_token = tokens.get('refresh_token', integ.refresh_token)
        integ.expires_at = now() + timedelta(seconds=tokens['expires_in'])
        integ.save(update_fields=['access_token', 'refresh_token', 'expires_at'])
        return integ.access_token