Data Storage
Apple Juicer keeps state in three places, and they fail differently. The filesystem holds the backups and is the only thing you must back up. PostgreSQL holds everything the worker derives, which you can rebuild by re-indexing. Redis holds the job queue, which you can lose without consequence.
Filesystem
Section titled “Filesystem”The backups are the source of truth and nothing copies them wholesale. Two paths matter:
- Backup data mounts read-only into the backend and worker (default
./data→/data/ios_backups). Apple Juicer reads it and never writes to it. - Temporary sandbox under
backup_paths.temp_path(default/tmp/apple_juicer) holds files extracted for a single download or parse. A StarletteBackgroundTaskdeletes each one after the response finishes.
Decrypted artifact databases are written to backup_paths.decrypted_path so the worker can index them and the UI can serve attachments without re-unlocking every time. That directory is plaintext — see Security.
PostgreSQL
Section titled “PostgreSQL”Postgres is everything the worker derives from a backup:
backups— the canonical list of discovered backups with device metadata, size, encryption flag, and the status lifecycle (DISCOVERED→DECRYPTED→INDEXING→INDEXED).- Artifact tables —
photo_assets,whatsapp_*,messages,notes,calendar_*,contacts, and the rest, one set per artifact type. Every row links back tobackups.idwithON DELETE CASCADE, so deleting a backup cleans up everything it produced. artifact_search_index— one denormalized text row per item, which is what global search queries.
The async SQLAlchemy engine reads its DSN from APPLE_JUICER_POSTGRES__DSN, defaulting to sqlite+aiosqlite:///./temp_data/apple_juicer.db so the tool runs without Postgres for tests and quick local trials. The schema is created and kept current by Alembic, which runs upgrade head automatically on backend startup.
Redis does two jobs and stores nothing sensitive:
- The queue.
core.queue.get_queue()returns a cached connection to thedefaultqueue with a 10-minute job timeout. - Job bookkeeping. RQ keeps its own job metadata, heartbeats, and results here.
Session tokens and decrypted data never touch Redis; they live in memory in the backend and worker processes. Point Redis wherever you like with APPLE_JUICER_REDIS__URL.
Backing it up
Section titled “Backing it up”The three layers map cleanly onto a recovery plan:
- Filesystem — snapshot or rsync the mounted backup directory. This is the only irreplaceable copy.
- PostgreSQL — use
pg_dumporpg_basebackupif you want to keep the indexes. If you don’t, you can drop the database and re-index from the backups. - Redis — skip it. A lost queue just means re-triggering any indexing run that was in flight.
Because decrypted payloads are never the system of record, recovery comes down to one thing: point the tool back at the backup directory and, if you didn’t keep Postgres, re-index.