Et live flysøgningssystem der kombinerer Spring Boot, Next.js, MongoDB og Google Flights-data — fra arkitektur og tekniske afvejninger til en reel production-incident jeg fejlsøgte og løste.
Bruger → Next.js (mdservice.uk)
└── /api/flights/* (Route Handler / proxy)
└── api.mdservice.uk (Spring Boot)
├── MongoDB Atlas — cache (TTL 30 min) + 7.629 lufthavne
└── SerpAPI → Google Flights
Flysøgninger cached i MongoDB med et TTL-index på 30 minutter (Duration.ofMinutes(30)). Det reducerer antallet af kald til SerpAPI markant på populære ruter, uden at data bliver forældet nok til at give brugerne forkerte priser.
Google Flights' API returnerer ikke et direkte bookinglink — kun tokens der skal sendes tilbage til SerpAPI for at få det rigtige redirect-link. Backend håndterer selve token-udvekslingen (fetchByToken) og følger derefter Googles redirect-kæde serverside med java.net.http.HttpClient, så brugeren lander direkte på det rigtige bookingsite i en ny fane — uden en mellemliggende popup eller loading-side.
Frontend forhindrer at brugeren overhovedet kan søge uden at vælge en lufthavn fra dropdown (ikke bare skrive fri tekst). Backend validerer derudover at koderne matcher IATA-formatet og rent faktisk findes i databasen, samt at origin og destination ikke er identiske — så useriøse eller ugyldige requests aldrig når frem til SerpAPI og spilder API-kvote.
Et konkret eksempel på fejlsøgning i produktion — fra symptom til root cause.
Efter en resize af Linode-serveren (opgradering af RAM) stoppede GitHub Actions-deploys med at fejle: "dial tcp ***:22: i/o timeout". Hjemmesiden kørte stadig fint — kun SSH var utilgængeligt.
Tjekkede Linodes Cloud Firewall-regler — port 22 var korrekt åben for indgående trafik. Ingen ændring der.
Via LISH-konsollen (out-of-band adgang) blev det bekræftet at sshd rent faktisk kørte og lyttede korrekt på 0.0.0.0:22 og :::22 med netstat/ps aux — så det var ikke sshd-processen selv.
iptables var ikke installeret på serveren (Alpine Linux), og der var ingen ufw. Et nmap-scan fra Linodes egen support bekræftede at port 22 blev rapporteret som "filtered" — dvs. pakker blev droppet et sted mellem netværket og processen.
apk info -e afslørede at nftables var installeret. Ruleset-dumpet viste en input-chain med "policy drop" og ingen eksplicit accept-regel for port 22 — sandsynligvis en standardregel der altid har været der, men som først blev relevant da forbindelsen skulle genetableres efter resize.
Tilføjede en eksplicit accept-regel direkte i kernel-ruleset via LISH: nft insert rule inet filter input tcp dport 22 accept. SSH virkede øjeblikkeligt igen, og CI/CD-pipelinen kunne deploye normalt.