Backend Contexts: Taxonomy & Catalog
Relevant source files
The following files were used as context for generating this wiki page:
The Taxonomy and Catalog contexts form the foundational structural layers of the ProductCompare backend. These modules are responsible for defining the classification systems (taxonomies), hierarchical relationships (taxons), and the core product entities (catalog) that enable typed product comparison. These contexts operate within a modular monolith architecture built on Phoenix and PostgreSQL.
The Taxonomy context manages tree-based classification through a closure table pattern, while the Catalog context serves as the central anchor for brands, products, and external source mappings. Together, they provide the necessary metadata for the Specs and Pricing modules to function.
Sources: README.md:1-12, ARCHITECTURE.md:10-14, 2026-03-03-product-compare-backend-mvp-plan.md:10-15
Core Architecture and Conventions
The backend follows a modular monolith design where context boundaries are strictly enforced. Logic for Taxonomy and Catalog resides in ProductCompare.Taxonomy and ProductCompare.Catalog, respectively, while data persistence is handled by schema-only modules under ProductCompareSchemas.
Database Standards
All relational tables within these contexts adhere to non-negotiable conventions:
- Primary Keys: Default to
bigint(id). - Entropy IDs: A
uuidv7(entropy_id) is generated by Postgres for all relational tables to provide unique, sortable identifiers. - Timestamps: Use
:utc_datetime_usecfor microsecond precision. - Durable Storage: PostgreSQL 18+ is the sole durable datastore.
Sources: backend_starting_guide.md:6-25, 2026-03-03-product-compare-backend-mvp-plan.md:52-57
Taxonomy Context
The Taxonomy context handles the classification of products into types and use-cases. It uses a closure table strategy to maintain hierarchies, allowing for efficient deep descendant and ancestor lookups.
Taxonomy Data Models
| Entity | Description |
|---|---|
| Taxonomy | Defines the classification system (e.g., "type" or "use_case"). |
| Taxon | A specific category node within a taxonomy (e.g., "Displays" or "Gaming"). |
| TaxonClosure | A join table tracking all ancestor-descendant relationships in the tree. |
| ProductTaxon | Maps products to specific taxons (tagging). |
| TaxonAlias | Optional aliases for taxons to support better discovery. |
Sources: 2026-03-03-product-compare-backend-mvp-plan.md:103-107, README.md:15-20
Hierarchy Management Flow
The move_taxon/2 operation is a critical workflow that ensures tree integrity by preventing cycles and atomically updating closure paths within a transaction.
The closure table implementation requires that for every node inserted, a self-closure row and rows linking to all parent lineages are maintained.
Sources: 2026-03-03-product-compare-backend-mvp-plan.md:188-198
Catalog Context
The Catalog context manages the lifecycle of product and brand records. It acts as the "anchor" for all spec claims and pricing data.
Catalog Data Models
The Catalog is organized around Brands and Products, with support for mapping to external vendor data via Sources.
| Entity | Field | Type | Constraint |
|---|---|---|---|
| Brand | name | String | Required |
| Product | slug | Slug | Unique |
| Product | primary_type_taxon_id | Foreign Key | References Taxon |
| ExternalProduct | external_id | String | Unique per Source |
| Source | name | String | Required |
Sources: 2026-03-03-product-compare-backend-mvp-plan.md:109-115, assets/src/routes/products/api.ts:8-14
Entity Relationship Diagram
The following diagram illustrates the relationship between Taxonomy, Catalog, and related specification metadata.
Key API Workflows
Taxonomy Management
The Taxonomy context exposes functions for tree traversal and maintenance:
create_taxon(attrs): Inserts a node and populates its closure paths.list_descendants(taxon_id): Retrieves all nodes under a given taxon.assign_use_case(product_id, use_case_taxon_id, ...): Tags a product with a specific use-case taxon.
Sources: 2026-03-03-product-compare-backend-mvp-plan.md:218-224
Catalog Discovery (GraphQL)
The Catalog is exposed to the frontend primarily via GraphQL Relay-style connections.
query BrowseProducts($first: Int) {
products(first: $first) {
edges {
node {
id
name
slug
brand {
id
name
}
}
}
}
}
The backend implements loadBrowseProducts and loadProductDetail to resolve these queries, ensuring that primary_type_taxon_id and brand associations are preloaded for efficient rendering.
Sources: assets/src/routes/catalog/api.ts:12-25, assets/src/routes/products/api.ts:31-43
Filtering and Search Indexing
The Catalog context supports advanced filtering through joins with the Specs module. Performance is maintained through specific indexing strategies:
- Taxonomy Traversal: Unique index on
taxon_closure(ancestor_id, descendant_id). - Product Lookups: Unique index on
products(slug)andproducts(primary_type_taxon_id). - Mapping Integrity: Unique index on
external_products(source_id, external_id).
Sources: 2026-03-03-product-compare-backend-mvp-plan.md:149-160
Conclusion
The Taxonomy and Catalog contexts provide the backbone of the ProductCompare platform. By utilizing a closure table for hierarchies and strict relational schemas for brands and products, the system ensures data integrity and high-performance querying for complex product comparisons. The use of UUIDv7 entropy IDs and microsecond timestamps across these contexts ensures that the data is both globally unique and temporally precise.