Skip to content

Dependencies and how long they last

Checked on 2026-08-21. Support dates are the kind of fact that is easy to remember wrongly, so every one here was read from a source rather than recalled, and the sources are at the bottom. Anything unverified says so.

The point of this page is not the inventory — package.json and pyproject.toml are the inventory. It is the horizon: what forces an upgrade, and when.

The clock that matters most

What Deadline Why it bites
Google Play target API 36 31 Aug 2026 (extension to 1 Nov 2026) New apps and updates must target Android 16. We already comply — Expo SDK 54 targets API 36
Node 22 maintenance ends 30 Apr 2027 Build tooling only; nothing ships to a user
Postgres 16 end of life 09 Nov 2028 Neon would migrate long before
Python 3.12 security-only until 31 Oct 2028 The container pins 3.12

Nothing here is urgent. The one with a date inside the next year is the Play requirement, and Expo has already handled it.

Mobile

Package Version Notes
Expo SDK 54 Released 10 Sep 2025. Three releases behind: 57 is current. Expo ships three SDKs a year
React Native 0.81.5 What SDK 54 pins
React 19.1.0 What SDK 54 pins
Node (build) 22.23.1 local SDK 54 requires ≥ 20.19.4
Android target API 36 (Android 16) From SDK 54
Android minimum API 24 Anything newer than that in the native module compiles and fails at runtime; native.yml's lintDebug (NewApi) is what catches it at build time — see gotchas
@sentry/react-native 7.2.x
expo-video 3.0.x Replaced expo-av, which is deprecated
zustand 5.0.x

What forces an Expo upgrade. Not age by itself. In order of likelihood: a new Play target-API deadline that SDK 54 does not meet; Expo Go, which only ever ships the newest SDK and is therefore already unusable here; and EAS Build eventually dropping old SDKs, which happens but is not on a published schedule.

Upgrading is not free. SDK upgrades have moved native APIs under this project before — expo-av to expo-video, expo-file-system to its /legacy entry point. Budget a build cycle and read the changelog for the camera and media modules specifically.

Backend

Package Constraint Notes
Python >=3.11, container runs 3.12 3.12 gets security fixes until 31 Oct 2028
FastAPI >=0.115 Pre-1.0; minor releases can still break
SQLAlchemy >=2.0.36
Alembic >=1.14
psycopg >=3.2 Prepares statements — see the note about connection pooling in gotchas
Pydantic >=2.9
boto3 / botocore >=1.35 1.36 changed upload checksum defaults and broke presigned PUTs to R2. Pinned behaviour, not version — see app/services/storage.py
APScheduler >=3.10 In-process, which is why there can only be one machine
sentry-sdk >=2.18
PostgreSQL 16 EOL 09 Nov 2028. Neon runs 16.15

The local development database is postgres:16-alpine, deliberately the same major version as production: a difference there is the kind of bug that only appears in production.

Already dead, and what replaced it

Worth knowing so nobody reintroduces them.

  • FCM Legacy API — shut down by Google in 2024. The eas credentials menu still offers it, directly above the option that works. Use FCM V1 with a Google service account key.
  • expo-av — deprecated; this project uses expo-video.
  • ffmpeg-kit-react-native — deprecated and its binaries withdrawn from Maven Central. This is why the native engine is written against MediaCodec directly rather than wrapping FFmpeg.
  • Expo Go for this project — it ships only the newest SDK. Use a development build.

What is pinned, and what is not

pyproject.toml declares >= ranges as the source of truth — the same constraints listed above — and backend/requirements.lock (committed, regenerated with uv pip compile pyproject.toml -o requirements.lock) pins the exact resolved set that backend/Dockerfile installs in its deps stage. A rebuild of the same git tag installs the same dependency graph; the botocore checksum change that arrived unannounced predates the lock file.

requirements.lock is the only lock file that counts. A backend/uv.lock may appear if you run uv commands in backend/; it is gitignored, nothing installs from it, and it is not kept in step with anything.

The mobile side is pinned by package-lock.json and by Expo's own version constraints, which is stricter.

Sources