Architecture Overview
Technical architecture of FilterIQ for developers.
This page describes the technical architecture of FilterIQ for developers who want to understand how the system works, build custom integrations, or troubleshoot issues.
System Diagram
┌──────────────────────────────────────────────────────────────┐
│ SHOPIFY STOREFRONT │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Theme App Extension (JavaScript + Liquid) │ │
│ │ ├── Search Widget (autocomplete, results rendering) │ │
│ │ ├── Filter Sidebar (faceted filtering UI) │ │
│ │ └── Event Tracking (clicks, impressions, conversions) │ │
│ └──────────────────┬─────────────────────────────────────┘ │
│ │ │
│ ┌──────────────────▼─────────────────────────────────────┐ │
│ │ Shopify App Proxy (/apps/search-filter/*) │ │
│ └──────────────────┬─────────────────────────────────────┘ │
└─────────────────────┼────────────────────────────────────────┘
│ HTTPS
┌─────────────────────▼────────────────────────────────────────┐
│ BACKEND API SERVER │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Search API │ │ Config API │ │ Analytics API │ │
│ │ /api/search │ │ /api/config │ │ /api/analytics │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────────┘ │
│ │ │ │ │
│ ┌──────▼──────────────────▼──────────────────▼───────────┐ │
│ │ Service Layer │ │
│ │ ├── Search Service (query processing, ranking) │ │
│ │ ├── Filter Service (facet configuration) │ │
│ │ ├── Merchandising Service (boost/bury/pin/hide rules) │ │
│ │ ├── Sync Service (Shopify → search engine indexing) │ │
│ │ └── Analytics Service (event aggregation, reporting) │ │
│ └──────┬───────────────────┬─────────────────┬───────────┘ │
│ │ │ │ │
│ ┌──────▼───────┐ ┌───────▼──────┐ ┌───────▼───────────┐ │
│ │ Search │ │ Database │ │ Cache │ │
│ │ Engine │ │ (PostgreSQL) │ │ Layer │ │
│ └──────────────┘ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐
│ SHOPIFY ADMIN │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ Embedded Admin App (React Router) │ │
│ │ ├── Dashboard (overview, sync status) │ │
│ │ ├── Search Config (attributes, synonyms, autocomplete) │ │
│ │ ├── Filter Config (filter types, ordering, presets) │ │
│ │ ├── Merchandising (pin, boost, demote, hide, rules) │ │
│ │ └── Analytics (search reports, filter reports) │ │
│ └──────────────────┬─────────────────────────────────────┘ │
│ │ Authenticated API calls │
│ └─────────────────────────────────────────┘
└──────────────────────────────────────────────────────────────┘
Technology Stack
| Layer | Technology | Purpose |
|---|---|---|
| Storefront | Liquid + JavaScript (Theme App Extension) | Search UI, filter UI, event tracking |
| Admin | React Router 7, Polaris, TypeScript | Admin dashboard |
| API Gateway | Shopify App Proxy | Secure routing from storefront to backend |
| Backend | Python, Pydantic | Business logic, API endpoints |
| Search Engine | Dedicated search engine | Full-text search, faceted filtering |
| Database | PostgreSQL | Configuration, analytics, user data |
| Cache | In-memory cache | Search cache, session data, rate limiting |
| Frontend Hosting | Cloud hosting | Admin app hosting |
| Backend Hosting | Cloud hosting | API hosting |
Multi-Tenant Architecture
FilterIQ is a multi-tenant application. Shop identity is the isolation boundary; the following describes the intended shop-scoped design, not a claim of dedicated infrastructure:
- Database: All queries include a
shop_domainfilter. Row-Level Security (RLS) policies enforce tenant isolation at the database level - Search Engine: Each shop gets its own search index (named by shop domain)
- Cache: Cache keys are prefixed with shop domain
- API: Authentication depends on the entry point: Shopify session JWT, verified app-proxy HMAC, verified webhook signature or authenticated internal service context. An unsigned shop identifier does not establish identity.
Separate product indexes do not mean separate servers or clusters. Confirm deployment-specific isolation evidence for your security review.
Authentication Flow
1. Merchant installs app → Shopify OAuth flow
2. Shopify provides access token → stored in the database
3. Admin requests use Shopify session tokens (JWT)
4. Storefront requests go through App Proxy; the signed request must be verified
5. The receiving service validates its supported authentication context
6. Webhooks have a separate signature-verification path
Security rule: Use the verified context for the relevant entry point. Do not treat an unsigned shop_domain parameter as authentication.
Data Flow: Product Indexing
Shopify Product Webhook (create/update/delete)
↓
Backend Webhook Handler
↓
Validation + shop_domain extraction
↓
Product data transformation (Shopify format → search document)
↓
Search index update (add/update/delete document)
↓
Search results reflect the completed index update; verify sync state
Data Flow: Search Query
Shopper types in search bar
↓
Theme Extension JavaScript applies its configured input handling
↓
Request to /apps/search-filter/api/search?q=...
↓
Shopify App Proxy forwards to backend
↓
Backend: validate request, check cache
↓ (cache miss)
Backend: apply merchandising rules to query
↓
Search engine: execute search with filters and facets
↓
Backend: format results, cache response
↓
Response returns to the storefront; network and rendering time still apply
↓
Theme Extension renders results
API Endpoints
Storefront API (via App Proxy)
| Endpoint | Method | Purpose |
|---|---|---|
/apps/search-filter/api/search | GET | Execute search query |
/apps/search-filter/api/autocomplete | GET | Autocomplete suggestions |
/apps/search-filter/api/filters | GET | Get filter configuration |
/apps/search-filter/api/track | POST | Track analytics event |
Admin API (authenticated)
| Endpoint | Method | Purpose |
|---|---|---|
/api/config/search | GET, PUT | Search configuration |
/api/config/filters | GET, PUT | Filter configuration |
/api/config/merchandising | GET, PUT | Merchandising rules |
/api/config/synonyms | GET, PUT, DELETE | Synonym management |
/api/analytics/* | GET | Analytics reports |
/api/sync/status | GET | Product sync status |
Performance Characteristics
No repeatable benchmark artifact is linked for the earlier typical timings or bundle-size figures. Those figures are not established production measurements and should not be used as buying guarantees.
Measure distinct intervals separately:
| Interval | What it establishes | What it excludes |
|---|---|---|
| Search-engine processing | Work inside the search engine for a specified query | Proxy, network, browser and rendering |
| HTTP round trip | Request through the measured endpoint to response | Input handling and rendering after receipt |
| Input-to-visible results | Shopper input through visible settled results | Other themes, devices or catalogues not tested |
| Index freshness | Source update through verified searchable output | A guarantee for every webhook or sync |
Record the release, device, location, catalogue, query/filter set, concurrency, cold/warm cache state and sample count. Include errors and tail latency, not only the fastest response. Measure transferred assets from the actual published theme; a source-file size is not the page's total network cost.
Interface and Request Limits
The endpoint names above describe internal architecture, not a generally available public API. See the REST API boundary before building an integration. Confirm actual paths, authentication and versioning with the team.
Request limits depend on the route, configuration and environment. A rate-limit response must be handled as a limit, not an empty result. Use the supported client path and bounded retries; do not infer a throughput entitlement from this architecture guide. See the performance guide for a storefront measurement checklist.
