Immich schalen: Hoe we reverse geocoding opnieuw ontwierpen voor enorme fotobibliotheken

PixelUnion Team
6 min read
Immich schalen: Hoe we reverse geocoding opnieuw ontwierpen voor enorme fotobibliotheken

Introductie: De magie van weten “Waar”

Voor home lab-enthousiastelingen en voorstanders van gegevensprivacy is Immich uitgegroeid tot een toonaangevende zelf-gehoste oplossing voor het beheren van foto’s en video’s. Het biedt een krachtig, privé alternatief voor cloud-gebaseerde diensten. Een van de meest overtuigende functies is een stuk achtergrondmagie: reverse geocoding. Dit proces analyseert automatisch de GPS-coördinaten die zijn ingebed in de EXIF-gegevens van een foto en verrijkt deze met door mensen leesbare locatiecontext—de stad, staat en het land waar de afbeelding is gemaakt.

Zoals opgemerkt in de officiële Immich-documentatie, wordt deze krachtige mogelijkheid aangedreven door de uitgebreide GeoNames geografische database. Dit stelt Immich in staat om een eenvoudige set coördinaten om te zetten in betekenisvolle informatie die u kunt gebruiken voor het zoeken en organiseren van uw herinneringen.

Maar wat gebeurt er wanneer deze elegante, zelfstandige functie niet alleen voor één gebruiker moet werken, maar over een enorm, multi-tenant platform? Dit was de schaaluitdaging die we bij PixelUnion tegenkwamen, en het dwong ons om opnieuw na te denken over hoe deze magie wordt geleverd.

De uitdaging: Immich’s standaard geocoding op schaal

Om een betere oplossing te ontwerpen, moesten we eerst de strategische ontwerp van Immich’s standaardarchitectuur waarderen. De standaardbenadering is briljant voor het beoogde publiek van individuele gebruikers, maar de kernontwerpkeuzes creëren voorspelbare knelpunten wanneer deze wordt ingezet voor een grote gebruikersbasis met duizenden fotobibliotheken.

Hoe standaard Immich geocoding werkt

In een standaardopstelling downloadt Immich de GeoNames-dataset en laadt deze direct in een lokale PostgreSQL-databasetabel. Volgens de documentatie wordt dit importproces geactiveerd tijdens elke minor versie-upgrade, waardoor de locatiegegevens up-to-date blijven.

Het primaire voordeel van deze architectuur is duidelijk: het houdt alle gegevensverwerking volledig zelfstandig op de server van de gebruiker. Dit verbetert de privacy en operationele eenvoud, omdat er geen externe afhankelijkheden zijn voor deze kernfunctie. Voor een typische zelf-hoster die zijn persoonlijke bibliotheek beheert, is een databasetabel van ongeveer 100MB een perfect redelijke en efficiënte oplossing voor de snelle, lokale opzoekingen die zowel de locatieweergave als Immich’s “Smart Search”-functionaliteit aandrijven.

Het knelpunt in grote implementaties

Dit zelfstandige model begint af te breken in grootschalige, multi-user omgevingen zoals de onze bij PixelUnion. Het kernprobleem is database-bloat. Wanneer die enkele ~100MB geodata-tabel wordt gerepliceerd over honderden of duizenden individuele database-instanties, wordt de cumulatieve opslagoverhead enorm. Dit presenteerde aanzienlijke operationele uitdagingen, waardoor de moeilijkheid en kosten die gepaard gaan met het opschalen van onze zeer grote Postgres-infrastructuur drastisch toenamen.

Een secundair probleem was de repetitieve overhead van de importtaak zelf. Het proces van downloaden en laden van de dataset, dat na elke Immich-update draait, wordt een zeer inefficiënte en resource-intensieve taak wanneer deze wordt vermenigvuldigd over onze hele implementatie. We hadden een manier nodig om deze functie te centraliseren zonder de prestaties in gevaar te brengen.

Onze oplossing: Geocoding ontkoppelen met een microservice

Ons strategische doel was om de geocoding-functie te ontkoppelen van de primaire Immich-database. Deze architectuurverschuiving was ontworpen om meer flexibiliteit, efficiëntie en schaalbaarheid te leveren zonder Immich’s kern gebruikersgerichte functies te wijzigen. We wilden het schaalprobleem oplossen op infrastructuurniveau terwijl het gedrag van de applicatie consistent blijft.

De architectuurverschuiving van lokale tabel naar centrale API

Onze oplossing was om de directe databasequery te vervangen door een eenvoudige API-aanroep naar een toegewijde microservice. In plaats van dat elke Immich-instantie zijn eigen kopie van de GeoNames-gegevens onderhoudt, draaien we nu een enkele, gecentraliseerde geocoding-microservice binnen ons cluster. Deze service bevat de GeoNames-gegevens en stelt API-endpoints bloot om zowel reverse geocoding-verzoeken als plaatsnaamzoekopdrachten voor alle Immich-instanties af te handelen.

Cruciaal is dat de microservice is ontworpen om gegevens te retourneren in exact hetzelfde formaat dat Immich verwacht van zijn interne databasequery. Dit maakt de architectuurwijziging volledig transparant voor de applicatielogica, waarbij alleen een kleine wijziging nodig is om verzoeken naar de nieuwe API te sturen in plaats van naar de lokale tabel.

Een technische blik op de code

Om dit te implementeren, introduceerden we een nieuwe omgevingsvariabele, GEODATA_API_URL, zoals te zien in onze commit naar de Immich-codebase. Deze variabele fungeert als een feature flag die een Immich-instantie vertelt of het de traditionele databasemethode of onze nieuwe externe API moet gebruiken voor zowel geocoding- als zoekfuncties.

De kernlogica, zichtbaar in de wijzigingen aan map.repository.ts en search.repository.ts, volgt een eenvoudige conditionele controle voor elke functie:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// In map.repository.ts
IF GEODATA_API_URL is configured:
   call reverseGeocodeViaApi(point, GEODATA_API_URL)
ELSE:
   call reverseGeocodeViaDatabase(point)

// In search.repository.ts
IF GEODATA_API_URL is configured:
   call searchPlacesViaApi(placeName, GEODATA_API_URL)
ELSE:
   call searchPlacesViaDatabase(placeName)

Deze elegante wijziging is krachtig om twee redenen. Ten eerste maakt het de nieuwe functie een opt-in verbetering, waardoor perfecte achterwaartse compatibiliteit behouden blijft voor alle bestaande Immich-gebruikers. Ten tweede biedt het een schone, configureerbare weg voor geschaalde implementaties zoals de onze om de volledige geodata-werkbelasting te offloaden zonder een complexe of invasieve fork van de hoofdapplicatie te vereisen.

De impact: Meetbare winsten en een schaalbaardere Immich

Deze architectuurwijzigingen waren niet alleen theoretische verbeteringen; ze resulteerden in significante, meetbare verbeteringen aan de efficiëntie, kosteneffectiviteit en onderhoudbaarheid van ons platform.

Gerealiseerde belangrijke voordelen

  • Drastische database-afslanking: De meest directe overwinning was een dramatische vermindering van de grootte van elke Immich-database-instantie. Door de ~100MB geodata-tabel uit de database van elke gebruiker te verwijderen, hebben we een enorme hoeveelheid opslag teruggewonnen over ons cluster.
  • Vereenvoudigde updates: Onze wijziging elimineert volledig de geodata-importtaak die Immich eerder uitvoerde na elke update. Dit bespaart aanzienlijke tijd en rekenresources tijdens onze platformbrede updatecycli. Dit wordt bevestigd door de nieuwe logica in de code, die expliciet logt dat het ’lokale geodata-import overslaat’ wanneer onze externe API is geconfigureerd.
  • Verbeterde schaalbaarheid: Met een kleinere database-footprint is de hele Immich-implementatie eenvoudiger te beheren, back-uppen en schalen. Bovendien verbetert het centraliseren van de logica de prestaties en consistentie van zowel locatiegegevensverrijking als zoekopdrachten over het platform, waardoor we meer gebruikers efficiënter en kosteneffectiever kunnen ondersteunen.

Open voor iedereen

We geloven in de kracht van open source en het teruggeven aan de gemeenschappen die ongelooflijke tools zoals Immich bouwen. Deze oplossing is teruggedoneerd via onze publieke, open-source fork. U kunt de exacte implementatie inspecteren, van de nieuwe omgevingsvariabele tot de conditionele API-aanroepen, in de commit hieronder gelinkt.

Bekijk de volledige commit op GitHub

Slotgedachten

Onze reis van het identificeren van een kritiek schaalknelpunt tot het implementeren van een robuuste, ontkoppelde microservice-oplossing benadrukt een veelvoorkomende uitdaging in software engineering: een functie die perfect is voor één schaal kan een obstakel worden op een andere. Door het probleem zorgvuldig te analyseren en een flexibele, achterwaarts compatibele oplossing te implementeren, konden we Immich’s architectuur verbeteren voor onze behoeften terwijl we een waardevolle optie terugdroegen aan de bredere gemeenschap. Bij PixelUnion blijven we toegewijd aan open source en moedigen we iedereen in de home lab- en self-hosting-gemeenschappen aan om dit soort oplossingen te verkennen, aan te passen en op te bouwen.