Work in progress · Version 1.1, last updated 6 November 2026
Systems

Finder and search

Two Go services on AWS answer every dive-shop, course and website search, fed live from PADI Travel through change data capture.

Summary

The finder lets visitors find dive shops and courses by place, and powers the website search box. locator-api is the public finder API: it builds cards, prices and map pins. search-api owns every OpenSearch query and also answers the website search box directly. A Lambda pipeline keeps a PostGIS database and the search indexes in step with PADI Travel within 10 minutes.

Component Technology Role
locator-api Go, port 8080 Shops, shop pages, nearby, courses, map, suggest, filters.
search-api Go, port 8081 All OpenSearch queries for the finder (private) and website search suggest and results (public). Adds Google places to finder search-box suggestions (800 ms, best effort, not used for mainland China, Hong Kong or Macau).
Pipeline Lambdas Go ingest (PADI Travel changes), indexer (builds documents), rebuild (new index generations, rollback), members (member file), translate, crowdinhook and crowdinrelay (Crowdin translation and webhooks)
FinderDB Aurora PostgreSQL + PostGIS 40 PADI Travel tables, finder-owned tables, document store
OpenSearch Amazon OpenSearch Service Finder indexes and the Drupal content index

Timeouts nest so the caller always answers: search-api 2 s, locator-api to search-api 2.5 s, locator-api request 3 s.

Data sources

Feed From Path Cadence
Shops, courses, prices, places PADI Travel database AWS DMS, then Kinesis, then the ingest Lambda Continuous
Shop membership PADI member file S3 event, EventBridge, SQS, members Lambda On each new file
Finder text translations Crowdin translate Lambda, Crowdin AI, webhook On change, hourly safety net
Place enrichment Google Places search-api, per request Live

A shop appears only when both the member file and PADI Travel's own rules agree it should.

Components (C4 level 3)

Figure 14. Finder components.
Figure 14. Finder components.

Change data capture

A PADI Travel change reaches the live index within 10 minutes. Ingest applies a change only when it is newer than the last one stored for that row, so replays are safe. A full rebuild creates a new generation of all four indexes and switches them in one step; rollback points them back.

Figure 15. Change data capture from PADI Travel.
Figure 15. Change data capture from PADI Travel.

Liveness of the feed is judged from stream age, hop-by-hop lag and a daily comparison of the index with FinderDB. A heartbeat through the stream is not possible because DMS does not replicate its own heartbeat table; a scheduled row in a replicated PADI Travel table would provide one.

Finder data model

FinderDB holds three layers: the PADI Travel tables copied by DMS (with 58 personal, banking and legal columns excluded), finder-owned tables, and a document store that the indexer turns into search documents. Finder translations exist only in FinderDB and cannot be rebuilt from PADI Travel, which is why the database has 14-day point-in-time recovery.

Figure 16. Finder entities.
Figure 16. Finder entities.
Index One document per Count (production, November 2026)
Shops shop, with its bookable experiences about 5,700
Courses shop and course pair about 130,000
Places place or shop, for lookup about 2,900 places and 5,700 shops
Reference exchange rates, filters 2
Website content (Drupal) published translation of a page about 34,500

Prices are stored in their own currency and converted at query time.

Finder query

Figure 17. Finder query. Edge caching of finder responses (60 s for prices, 2 minutes for filters) is planned, not yet in place.
Figure 17. Finder query. Edge caching of finder responses (60 s for prices, 2 minutes for filters) is planned, not yet in place.

When part of a query fails, the response names the failed section; the API returns 503 only when nothing could be searched.

The website search box queries finder indexes and Drupal content in one call. Drupal owns its content documents; the search service owns the index template, analysers and aliases. Each language has its own fields, and visitors see only their language.

Figure 18. Website search. Browsers call search-api through Cloudflare.
Figure 18. Website search. Browsers call search-api through Cloudflare.

Indexing website content

Figure 19. Content indexing.
Figure 19. Content indexing.

Environments and sizing

Development Staging Production
Compute 1 host per service 1 host per service Autoscaling groups behind load balancers: search 1 to 4, locator 1 to 3 hosts. One of each today; at least 2 across zones before launch.
Datastores Containers on the host Containers on the host OpenSearch Service: 1 node (m7g.large, 50 GB) today, 3 nodes with 1 replica before launch. Aurora Serverless v2, 1 to 8 capacity units: writer today, reader added before launch.
Data PADI Travel staging PADI Travel production PADI Travel production, dedicated stream
Origin protection Per-hostname client certificates from Cloudflare Same Load balancer mutual TLS, Cloudflare address ranges only