{
  "name": "FIN STUDIO Scale Lab 2026 — commerce catalog benchmark",
  "creator": "FIN STUDIO",
  "license": "CC BY 4.0",
  "generatedAt": "2026-09-24T11:45:49.531Z",
  "environment": {
    "host": {
      "os": "Windows_NT 10.0.26200",
      "platform": "win32",
      "cpuModel": "13th Gen Intel(R) Core(TM) i7-13700K",
      "logicalCpus": 24,
      "totalMemBytes": 34116042752,
      "node": "v24.0.0",
      "pgClient": "node-postgres 8.23.0",
      "physicalCores": 16
    },
    "docker": {
      "serverVersion": "27.5.1",
      "operatingSystem": "Docker Desktop",
      "kernelVersion": "6.18.33.2-microsoft-standard-WSL2",
      "ncpu": 24,
      "memTotalBytes": 16642662400,
      "container": "finsite-scalelab",
      "image": "postgres:16",
      "command": [
        "-c",
        "shared_buffers=1GB",
        "-c",
        "work_mem=32MB",
        "-c",
        "effective_cache_size=4GB",
        "-c",
        "maintenance_work_mem=512MB",
        "-c",
        "max_wal_size=4GB"
      ]
    },
    "client": "single node-postgres connection, sequential queries, 127.0.0.1 TCP, unnamed parameterized statements",
    "measurement": "wall-clock round trip via performance.now(); 20 warm-up + 300 measured iterations per read query; parameters drawn at random (seeded) from loaded data"
  },
  "postgresConfig": {
    "version": "PostgreSQL 16.15 (Debian 16.15-1.pgdg13+2) on x86_64-pc-linux-gnu, compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit",
    "settings": {
      "checkpoint_timeout": {
        "setting": "300",
        "unit": "s",
        "source": "default"
      },
      "default_statistics_target": {
        "setting": "100",
        "unit": null,
        "source": "default"
      },
      "effective_cache_size": {
        "setting": "524288",
        "unit": "8kB",
        "source": "command line"
      },
      "fsync": {
        "setting": "on",
        "unit": null,
        "source": "default"
      },
      "huge_pages": {
        "setting": "try",
        "unit": null,
        "source": "default"
      },
      "jit": {
        "setting": "on",
        "unit": null,
        "source": "default"
      },
      "maintenance_work_mem": {
        "setting": "524288",
        "unit": "kB",
        "source": "command line"
      },
      "max_parallel_workers": {
        "setting": "8",
        "unit": null,
        "source": "default"
      },
      "max_parallel_workers_per_gather": {
        "setting": "2",
        "unit": null,
        "source": "default"
      },
      "max_wal_size": {
        "setting": "4096",
        "unit": "MB",
        "source": "command line"
      },
      "random_page_cost": {
        "setting": "4",
        "unit": null,
        "source": "default"
      },
      "server_version": {
        "setting": "16.15 (Debian 16.15-1.pgdg13+2)",
        "unit": null,
        "source": "default"
      },
      "shared_buffers": {
        "setting": "131072",
        "unit": "8kB",
        "source": "command line"
      },
      "synchronous_commit": {
        "setting": "on",
        "unit": null,
        "source": "default"
      },
      "wal_level": {
        "setting": "replica",
        "unit": null,
        "source": "default"
      },
      "work_mem": {
        "setting": "32768",
        "unit": "kB",
        "source": "command line"
      }
    }
  },
  "queryDefinitions": {
    "Q0": {
      "label": "Baseline: SELECT 1 round trip (client + localhost/Docker network floor)",
      "sql": "SELECT 1"
    },
    "Q1": {
      "label": "PDP: product by slug + brand + category join",
      "sql": "SELECT p.id, p.sku, p.slug, p.name, p.price_cents, p.stock, p.is_active, p.attrs, p.updated_at,\n       b.name AS brand_name, b.slug AS brand_slug, c.name AS category_name, c.path AS category_path\nFROM products p\nJOIN brands b ON b.id = p.brand_id\nJOIN categories c ON c.id = p.category_id\nWHERE p.slug = $1"
    },
    "Q2": {
      "label": "Category listing page 1 (24, active, popularity desc)",
      "sql": "SELECT p.id, p.slug, p.name, p.price_cents, p.stock, p.popularity, b.name AS brand_name\nFROM products p\nJOIN brands b ON b.id = p.brand_id\nWHERE p.category_id = $1 AND p.is_active\nORDER BY p.popularity DESC, p.id DESC\nLIMIT 24"
    },
    "Q3_keyset": {
      "label": "Deep pagination ~page 200 (150-250), keyset cursor",
      "sql": "SELECT id, slug, name, price_cents, popularity\nFROM products\nWHERE is_active AND (popularity, id) < ($1, $2)\nORDER BY popularity DESC, id DESC\nLIMIT 24"
    },
    "Q3_offset": {
      "label": "ANTI-PATTERN: same depth via OFFSET",
      "sql": "SELECT id, slug, name, price_cents, popularity\nFROM products\nWHERE is_active\nORDER BY popularity DESC, id DESC\nOFFSET $1 LIMIT 24"
    },
    "Q3_keyset_p2000": {
      "label": "Deeper pagination ~page 2000 (1500-2500), keyset cursor",
      "sql": "SELECT id, slug, name, price_cents, popularity\nFROM products\nWHERE is_active AND (popularity, id) < ($1, $2)\nORDER BY popularity DESC, id DESC\nLIMIT 24"
    },
    "Q3_offset_p2000": {
      "label": "ANTI-PATTERN: ~page 2000 via OFFSET",
      "sql": "SELECT id, slug, name, price_cents, popularity\nFROM products\nWHERE is_active\nORDER BY popularity DESC, id DESC\nOFFSET $1 LIMIT 24"
    },
    "Q4": {
      "label": "Faceted filter: subtree + 2-3 brands + price range + in stock + color, 24 rows",
      "sql": "SELECT p.id, p.slug, p.name, p.price_cents, p.stock, p.popularity\nFROM products p\nWHERE p.category_id IN (SELECT id FROM categories WHERE path LIKE $1)\n  AND p.is_active AND p.stock > 0\n  AND p.brand_id = ANY($2::int[])\n  AND p.price_cents BETWEEN $3 AND $4\n  AND p.attrs @> $5::jsonb\nORDER BY p.popularity DESC, p.id DESC\nLIMIT 24"
    },
    "Q5": {
      "label": "Facet counts: top 20 brands for the Q4 filter set (brand filter excluded)",
      "sql": "SELECT p.brand_id, b.name, count(*)::int AS n\nFROM products p\nJOIN brands b ON b.id = p.brand_id\nWHERE p.category_id IN (SELECT id FROM categories WHERE path LIKE $1)\n  AND p.is_active AND p.stock > 0\n  AND p.price_cents BETWEEN $2 AND $3\n  AND p.attrs @> $4::jsonb\nGROUP BY p.brand_id, b.name\nORDER BY n DESC, p.brand_id\nLIMIT 20"
    },
    "Q6": {
      "label": "Full-text search, 1-2 tokens, top 24 by ts_rank",
      "sql": "SELECT p.id, p.slug, p.name, p.price_cents, ts_rank(p.search, q) AS rank\nFROM products p, plainto_tsquery('simple', unaccent($1)) q\nWHERE p.search @@ q AND p.is_active\nORDER BY rank DESC, p.id DESC\nLIMIT 24"
    },
    "Q6_pop": {
      "label": "Full-text search, 1-2 tokens, top 24 by popularity",
      "sql": "SELECT p.id, p.slug, p.name, p.price_cents, p.popularity\nFROM products p\nWHERE p.search @@ plainto_tsquery('simple', unaccent($1)) AND p.is_active\nORDER BY p.popularity DESC, p.id DESC\nLIMIT 24"
    },
    "Q6_count_capped": {
      "label": "Search result count, capped at 1001 (\"1000+\")",
      "sql": "SELECT count(*)::int AS n\nFROM (SELECT 1 FROM products\n      WHERE search @@ plainto_tsquery('simple', unaccent($1)) AND is_active\n      LIMIT 1001) s"
    },
    "Q7": {
      "label": "B2B price resolution: 24 products x customer group",
      "sql": "SELECT p.id, p.price_cents AS list_price_cents,\n       COALESCE(cp.price_cents, p.price_cents) AS effective_price_cents,\n       (cp.price_cents IS NOT NULL) AS is_contract_price\nFROM products p\nLEFT JOIN customer_prices cp ON cp.customer_group_id = $2 AND cp.product_id = p.id\nWHERE p.id = ANY($1::bigint[])"
    },
    "Q8": {
      "label": "Incremental sync: UPDATE price+stock for 1,000 products, one transaction",
      "sql": "UPDATE products p\nSET price_cents = v.price_cents, stock = v.stock, updated_at = now()\nFROM unnest($1::bigint[], $2::int[], $3::int[]) AS v(id, price_cents, stock)\nWHERE p.id = v.id"
    }
  },
  "datasets": [
    {
      "products": 10000,
      "status": "ok",
      "categories": 100,
      "brands": 5000,
      "customerGroups": 50,
      "customerPrices": 2599,
      "loadSeconds": 0.744,
      "loadBreakdown": {
        "generateSeconds": 0.193,
        "indexSeconds": 0.208,
        "vacuumAnalyzeSeconds": 0.259,
        "steps": {
          "schema": 0.07,
          "generate.functions": 0.004,
          "generate.categories": 0.009,
          "generate.brands": 0.018,
          "generate.customer_groups": 0.004,
          "generate.products": 0.146,
          "generate.customer_prices": 0.012,
          "indexes.constraints_unique": 0.069,
          "indexes.idx_cat_pop": 0.017,
          "indexes.idx_cat_price": 0.02,
          "indexes.idx_active_pop": 0.016,
          "indexes.idx_brand": 0.016,
          "indexes.idx_search": 0.016,
          "indexes.idx_attrs": 0.009,
          "indexes.idx_categories": 0.02,
          "indexes.customer_prices_pk": 0.012,
          "indexes.foreign_keys": 0.009,
          "indexes.identity_sequence": 0.004,
          "vacuum_analyze": 0.259
        }
      },
      "ingestRowsPerSec": 68493,
      "sizes": {
        "tableBytes": 3907584,
        "indexBytes": 3244032,
        "totalBytes": 7151616
      },
      "perTable": {
        "brands": {
          "tableBytes": 303104,
          "indexBytes": 311296,
          "totalBytes": 614400
        },
        "products": {
          "tableBytes": 3325952,
          "indexBytes": 2752512,
          "totalBytes": 6078464
        },
        "categories": {
          "tableBytes": 57344,
          "indexBytes": 65536,
          "totalBytes": 122880
        },
        "customer_groups": {
          "tableBytes": 49152,
          "indexBytes": 16384,
          "totalBytes": 65536
        },
        "customer_prices": {
          "tableBytes": 172032,
          "indexBytes": 98304,
          "totalBytes": 270336
        }
      },
      "perIndex": {
        "products_slug_key": 573440,
        "products_search_idx": 376832,
        "products_sku_key": 335872,
        "products_active_pop_idx": 319488,
        "products_cat_pop_idx": 319488,
        "products_cat_price_idx": 319488,
        "products_pkey": 245760,
        "brands_slug_key": 180224,
        "products_brand_idx": 139264,
        "brands_pkey": 131072,
        "products_attrs_idx": 122880,
        "customer_prices_pkey": 98304,
        "categories_slug_key": 16384,
        "customer_groups_pkey": 16384,
        "categories_path_idx": 16384,
        "categories_parent_idx": 16384,
        "categories_pkey": 16384
      },
      "counts": {
        "products": 10000,
        "active_products": 9490,
        "categories": 100,
        "leaf_categories": 79,
        "brands": 5000,
        "customer_groups": 50,
        "customer_prices": 2599,
        "products_with_contract_price": 501,
        "largest_leaf_products": 1140,
        "top_brand_products": 777,
        "out_of_stock_products": 1523
      },
      "keysetMatchesOffset": true,
      "queries": {
        "Q0": {
          "p50": 0.537,
          "p95": 0.82,
          "p99": 0.93,
          "max": 1.034,
          "min": 0.341,
          "mean": 0.567,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q1": {
          "p50": 0.687,
          "p95": 0.998,
          "p99": 1.217,
          "max": 1.585,
          "min": 0.481,
          "mean": 0.719,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q2": {
          "p50": 0.706,
          "p95": 1.003,
          "p99": 1.103,
          "max": 1.189,
          "min": 0.471,
          "mean": 0.742,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset": {
          "p50": 0.645,
          "p95": 1.059,
          "p99": 1.135,
          "max": 1.228,
          "min": 0.411,
          "mean": 0.681,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_offset": {
          "p50": 1.672,
          "p95": 3.292,
          "p99": 3.829,
          "max": 4.081,
          "min": 1.047,
          "mean": 1.899,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset_p2000": {
          "status": "skipped",
          "reason": "only 9490 active products; page 2500 needs 60000"
        },
        "Q3_offset_p2000": {
          "status": "skipped",
          "reason": "only 9490 active products; page 2500 needs 60000"
        },
        "Q4": {
          "p50": 0.826,
          "p95": 1.134,
          "p99": 1.378,
          "max": 1.41,
          "min": 0.584,
          "mean": 0.861,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 2.35
        },
        "Q5": {
          "p50": 1.233,
          "p95": 1.749,
          "p99": 2.072,
          "max": 2.892,
          "min": 0.81,
          "mean": 1.266,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 16.923
        },
        "Q6": {
          "p50": 0.835,
          "p95": 1.468,
          "p99": 1.8,
          "max": 2.025,
          "min": 0.471,
          "mean": 0.889,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 16.24
        },
        "Q6_pop": {
          "p50": 0.822,
          "p95": 1.354,
          "p99": 1.666,
          "max": 1.927,
          "min": 0.402,
          "mean": 0.868,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 17.32
        },
        "Q6_count_capped": {
          "p50": 0.644,
          "p95": 1.061,
          "p99": 1.337,
          "max": 1.844,
          "min": 0.414,
          "mean": 0.692,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q7": {
          "p50": 0.639,
          "p95": 0.885,
          "p99": 0.994,
          "max": 1.418,
          "min": 0.499,
          "mean": 0.676,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q8": {
          "p50": 32.833,
          "p95": 40.702,
          "p99": 41.12,
          "max": 41.12,
          "min": 29.587,
          "mean": 33.536,
          "iterations": 20,
          "note": "batch time = BEGIN + UPDATE + COMMIT round trips; COMMIT includes WAL flush (synchronous_commit=on)",
          "updateStatementP50": 23.564,
          "commitP50": 7.648,
          "warmup": 5,
          "batchSize": 1000,
          "rowsUpdated": 20000,
          "rowsPerSecAtP50": 30457,
          "rowsPerSecOverall": 29819
        },
        "Q9": {
          "status": "derived",
          "rowsPerSec": 68493,
          "note": "products rows / seconds of generate.sql step \"products\" (in-database generation + insert, no indexes)"
        }
      }
    },
    {
      "products": 100000,
      "status": "ok",
      "categories": 1000,
      "brands": 5000,
      "customerGroups": 50,
      "customerPrices": 24729,
      "loadSeconds": 2.94,
      "loadBreakdown": {
        "generateSeconds": 1.405,
        "indexSeconds": 0.914,
        "vacuumAnalyzeSeconds": 0.516,
        "steps": {
          "schema": 0.069,
          "generate.functions": 0.004,
          "generate.categories": 0.019,
          "generate.brands": 0.015,
          "generate.customer_groups": 0.004,
          "generate.products": 1.319,
          "generate.customer_prices": 0.044,
          "indexes.constraints_unique": 0.389,
          "indexes.idx_cat_pop": 0.055,
          "indexes.idx_cat_price": 0.056,
          "indexes.idx_active_pop": 0.058,
          "indexes.idx_brand": 0.047,
          "indexes.idx_search": 0.116,
          "indexes.idx_attrs": 0.086,
          "indexes.idx_categories": 0.021,
          "indexes.customer_prices_pk": 0.025,
          "indexes.foreign_keys": 0.056,
          "indexes.identity_sequence": 0.005,
          "vacuum_analyze": 0.516
        }
      },
      "ingestRowsPerSec": 75815,
      "sizes": {
        "tableBytes": 34701312,
        "indexBytes": 25886720,
        "totalBytes": 60588032
      },
      "perTable": {
        "brands": {
          "tableBytes": 303104,
          "indexBytes": 311296,
          "totalBytes": 614400
        },
        "products": {
          "tableBytes": 32882688,
          "indexBytes": 24584192,
          "totalBytes": 57466880
        },
        "categories": {
          "tableBytes": 139264,
          "indexBytes": 180224,
          "totalBytes": 319488
        },
        "customer_groups": {
          "tableBytes": 49152,
          "indexBytes": 16384,
          "totalBytes": 65536
        },
        "customer_prices": {
          "tableBytes": 1327104,
          "indexBytes": 794624,
          "totalBytes": 2121728
        }
      },
      "perIndex": {
        "products_slug_key": 5660672,
        "products_sku_key": 3178496,
        "products_cat_pop_idx": 3022848,
        "products_active_pop_idx": 3022848,
        "products_cat_price_idx": 3022848,
        "products_search_idx": 2285568,
        "products_pkey": 2260992,
        "products_attrs_idx": 1302528,
        "products_brand_idx": 827392,
        "customer_prices_pkey": 794624,
        "brands_slug_key": 180224,
        "brands_pkey": 131072,
        "categories_slug_key": 57344,
        "categories_path_idx": 49152,
        "categories_pkey": 40960,
        "categories_parent_idx": 32768,
        "customer_groups_pkey": 16384
      },
      "counts": {
        "products": 100000,
        "active_products": 95066,
        "categories": 1000,
        "leaf_categories": 800,
        "brands": 5000,
        "customer_groups": 50,
        "customer_prices": 24729,
        "products_with_contract_price": 4888,
        "largest_leaf_products": 3567,
        "top_brand_products": 8077,
        "out_of_stock_products": 14926
      },
      "keysetMatchesOffset": true,
      "queries": {
        "Q0": {
          "p50": 0.417,
          "p95": 0.572,
          "p99": 0.683,
          "max": 0.757,
          "min": 0.274,
          "mean": 0.432,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q1": {
          "p50": 0.706,
          "p95": 1.176,
          "p99": 1.421,
          "max": 1.615,
          "min": 0.537,
          "mean": 0.777,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q2": {
          "p50": 0.709,
          "p95": 1.034,
          "p99": 1.567,
          "max": 1.82,
          "min": 0.54,
          "mean": 0.759,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset": {
          "p50": 0.589,
          "p95": 0.815,
          "p99": 0.914,
          "max": 0.989,
          "min": 0.459,
          "mean": 0.615,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_offset": {
          "p50": 2.373,
          "p95": 3.415,
          "p99": 3.995,
          "max": 4.598,
          "min": 1.314,
          "mean": 2.398,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset_p2000": {
          "p50": 0.558,
          "p95": 0.774,
          "p99": 0.888,
          "max": 1.889,
          "min": 0.452,
          "mean": 0.589,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_offset_p2000": {
          "p50": 16.311,
          "p95": 27.305,
          "p99": 38.418,
          "max": 44.902,
          "min": 11.081,
          "mean": 17.239,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q4": {
          "p50": 1.24,
          "p95": 2.896,
          "p99": 4.056,
          "max": 6.004,
          "min": 0.674,
          "mean": 1.483,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1.937
        },
        "Q5": {
          "p50": 2.644,
          "p95": 5.739,
          "p99": 7.11,
          "max": 8.114,
          "min": 1.053,
          "mean": 2.998,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 15.233
        },
        "Q6": {
          "p50": 0.951,
          "p95": 2.62,
          "p99": 4.243,
          "max": 6.202,
          "min": 0.499,
          "mean": 1.286,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 19.913
        },
        "Q6_pop": {
          "p50": 0.943,
          "p95": 3.964,
          "p99": 4.723,
          "max": 6.169,
          "min": 0.519,
          "mean": 1.433,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 18.16
        },
        "Q6_count_capped": {
          "p50": 0.801,
          "p95": 1.528,
          "p99": 1.886,
          "max": 2.014,
          "min": 0.456,
          "mean": 0.919,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q7": {
          "p50": 0.694,
          "p95": 0.944,
          "p99": 1.222,
          "max": 2.827,
          "min": 0.593,
          "mean": 0.743,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q8": {
          "p50": 52.073,
          "p95": 59.884,
          "p99": 61.021,
          "max": 61.021,
          "min": 36.019,
          "mean": 51.603,
          "iterations": 20,
          "note": "batch time = BEGIN + UPDATE + COMMIT round trips; COMMIT includes WAL flush (synchronous_commit=on)",
          "updateStatementP50": 43.917,
          "commitP50": 7.609,
          "warmup": 5,
          "batchSize": 1000,
          "rowsUpdated": 20000,
          "rowsPerSecAtP50": 19204,
          "rowsPerSecOverall": 19379
        },
        "Q9": {
          "status": "derived",
          "rowsPerSec": 75815,
          "note": "products rows / seconds of generate.sql step \"products\" (in-database generation + insert, no indexes)"
        }
      }
    },
    {
      "products": 1000000,
      "status": "ok",
      "categories": 2000,
      "brands": 5000,
      "customerGroups": 50,
      "customerPrices": 250326,
      "loadSeconds": 21.195,
      "loadBreakdown": {
        "generateSeconds": 14.423,
        "indexSeconds": 5.96,
        "vacuumAnalyzeSeconds": 0.54,
        "steps": {
          "schema": 0.066,
          "generate.functions": 0.004,
          "generate.categories": 0.028,
          "generate.brands": 0.02,
          "generate.customer_groups": 0.004,
          "generate.products": 14.047,
          "generate.customer_prices": 0.32,
          "indexes.constraints_unique": 2.627,
          "indexes.idx_cat_pop": 0.407,
          "indexes.idx_cat_price": 0.334,
          "indexes.idx_active_pop": 0.314,
          "indexes.idx_brand": 0.214,
          "indexes.idx_search": 0.97,
          "indexes.idx_attrs": 0.541,
          "indexes.idx_categories": 0.021,
          "indexes.customer_prices_pk": 0.09,
          "indexes.foreign_keys": 0.438,
          "indexes.identity_sequence": 0.004,
          "vacuum_analyze": 0.54
        }
      },
      "ingestRowsPerSec": 71190,
      "sizes": {
        "tableBytes": 342540288,
        "indexBytes": 242991104,
        "totalBytes": 585531392
      },
      "perTable": {
        "brands": {
          "tableBytes": 303104,
          "indexBytes": 311296,
          "totalBytes": 614400
        },
        "products": {
          "tableBytes": 328851456,
          "indexBytes": 234455040,
          "totalBytes": 563306496
        },
        "categories": {
          "tableBytes": 237568,
          "indexBytes": 286720,
          "totalBytes": 524288
        },
        "customer_groups": {
          "tableBytes": 49152,
          "indexBytes": 16384,
          "totalBytes": 65536
        },
        "customer_prices": {
          "tableBytes": 13099008,
          "indexBytes": 7921664,
          "totalBytes": 21020672
        }
      },
      "perIndex": {
        "products_slug_key": 57556992,
        "products_sku_key": 31563776,
        "products_active_pop_idx": 29990912,
        "products_cat_price_idx": 29974528,
        "products_cat_pop_idx": 29966336,
        "products_pkey": 22487040,
        "products_search_idx": 18620416,
        "customer_prices_pkey": 7921664,
        "products_attrs_idx": 7184384,
        "products_brand_idx": 7110656,
        "brands_slug_key": 180224,
        "brands_pkey": 131072,
        "categories_slug_key": 98304,
        "categories_path_idx": 81920,
        "categories_pkey": 65536,
        "categories_parent_idx": 40960,
        "customer_groups_pkey": 16384
      },
      "counts": {
        "products": 1000000,
        "active_products": 950203,
        "categories": 2000,
        "leaf_categories": 1600,
        "brands": 5000,
        "customer_groups": 50,
        "customer_prices": 250326,
        "products_with_contract_price": 49728,
        "largest_leaf_products": 25237,
        "top_brand_products": 81310,
        "out_of_stock_products": 149750
      },
      "keysetMatchesOffset": true,
      "queries": {
        "Q0": {
          "p50": 0.402,
          "p95": 0.576,
          "p99": 0.739,
          "max": 1.709,
          "min": 0.281,
          "mean": 0.426,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q1": {
          "p50": 0.681,
          "p95": 0.987,
          "p99": 1.067,
          "max": 1.108,
          "min": 0.511,
          "mean": 0.717,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q2": {
          "p50": 0.759,
          "p95": 1.098,
          "p99": 1.209,
          "max": 1.281,
          "min": 0.566,
          "mean": 0.8,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset": {
          "p50": 0.72,
          "p95": 1.072,
          "p99": 1.181,
          "max": 1.56,
          "min": 0.468,
          "mean": 0.759,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_offset": {
          "p50": 4.143,
          "p95": 5.501,
          "p99": 6.349,
          "max": 7.494,
          "min": 2.367,
          "mean": 4.193,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset_p2000": {
          "p50": 0.569,
          "p95": 0.762,
          "p99": 0.853,
          "max": 1.053,
          "min": 0.447,
          "mean": 0.597,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_offset_p2000": {
          "p50": 31.464,
          "p95": 42.728,
          "p99": 51.325,
          "max": 87.539,
          "min": 22.587,
          "mean": 32.455,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q4": {
          "p50": 5.989,
          "p95": 33.391,
          "p99": 40.323,
          "max": 244.332,
          "min": 1.179,
          "mean": 11.521,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 6.233
        },
        "Q5": {
          "p50": 18.647,
          "p95": 38.606,
          "p99": 46.934,
          "max": 60.872,
          "min": 1.292,
          "mean": 18.866,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 19.923
        },
        "Q6": {
          "p50": 2.684,
          "p95": 21.721,
          "p99": 35.411,
          "max": 51.495,
          "min": 0.584,
          "mean": 7.026,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 21.657
        },
        "Q6_pop": {
          "p50": 2.307,
          "p95": 32.376,
          "p99": 52.548,
          "max": 69.957,
          "min": 0.643,
          "mean": 4.934,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 21.917
        },
        "Q6_count_capped": {
          "p50": 2.506,
          "p95": 4.862,
          "p99": 5.597,
          "max": 8.938,
          "min": 0.582,
          "mean": 2.531,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q7": {
          "p50": 0.741,
          "p95": 1.049,
          "p99": 1.16,
          "max": 1.224,
          "min": 0.557,
          "mean": 0.767,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q8": {
          "p50": 38.27,
          "p95": 48.606,
          "p99": 53.425,
          "max": 53.425,
          "min": 34.04,
          "mean": 40.577,
          "iterations": 20,
          "note": "batch time = BEGIN + UPDATE + COMMIT round trips; COMMIT includes WAL flush (synchronous_commit=on)",
          "updateStatementP50": 30.56,
          "commitP50": 7.054,
          "warmup": 5,
          "batchSize": 1000,
          "rowsUpdated": 20000,
          "rowsPerSecAtP50": 26130,
          "rowsPerSecOverall": 24644
        },
        "Q9": {
          "status": "derived",
          "rowsPerSec": 71190,
          "note": "products rows / seconds of generate.sql step \"products\" (in-database generation + insert, no indexes)"
        }
      }
    },
    {
      "products": 5000000,
      "status": "ok",
      "categories": 2000,
      "brands": 5000,
      "customerGroups": 50,
      "customerPrices": 1250416,
      "loadSeconds": 130.73,
      "loadBreakdown": {
        "generateSeconds": 80.617,
        "indexSeconds": 47.409,
        "vacuumAnalyzeSeconds": 1.203,
        "steps": {
          "schema": 0.066,
          "generate.functions": 0.004,
          "generate.categories": 0.029,
          "generate.brands": 0.016,
          "generate.customer_groups": 0.004,
          "generate.products": 78.443,
          "generate.customer_prices": 2.121,
          "indexes.constraints_unique": 15.322,
          "indexes.idx_cat_pop": 7.381,
          "indexes.idx_cat_price": 6.844,
          "indexes.idx_active_pop": 3.54,
          "indexes.idx_brand": 1.132,
          "indexes.idx_search": 6.657,
          "indexes.idx_attrs": 3.152,
          "indexes.idx_categories": 0.039,
          "indexes.customer_prices_pk": 0.443,
          "indexes.foreign_keys": 2.895,
          "indexes.identity_sequence": 0.004,
          "vacuum_analyze": 1.203
        }
      },
      "ingestRowsPerSec": 63741,
      "sizes": {
        "tableBytes": 1715380224,
        "indexBytes": 1190887424,
        "totalBytes": 2906267648
      },
      "perTable": {
        "brands": {
          "tableBytes": 303104,
          "indexBytes": 311296,
          "totalBytes": 614400
        },
        "products": {
          "tableBytes": 1649500160,
          "indexBytes": 1150812160,
          "totalBytes": 2800312320
        },
        "categories": {
          "tableBytes": 237568,
          "indexBytes": 286720,
          "totalBytes": 524288
        },
        "customer_groups": {
          "tableBytes": 49152,
          "indexBytes": 16384,
          "totalBytes": 65536
        },
        "customer_prices": {
          "tableBytes": 65290240,
          "indexBytes": 39460864,
          "totalBytes": 104751104
        }
      },
      "perIndex": {
        "products_slug_key": 292855808,
        "products_sku_key": 157736960,
        "products_active_pop_idx": 149872640,
        "products_cat_price_idx": 149798912,
        "products_cat_pop_idx": 149766144,
        "products_pkey": 112328704,
        "products_search_idx": 69689344,
        "customer_prices_pkey": 39460864,
        "products_brand_idx": 35201024,
        "products_attrs_idx": 33562624,
        "brands_slug_key": 180224,
        "brands_pkey": 131072,
        "categories_slug_key": 98304,
        "categories_path_idx": 81920,
        "categories_pkey": 65536,
        "categories_parent_idx": 40960,
        "customer_groups_pkey": 16384
      },
      "counts": {
        "products": 5000000,
        "active_products": 4750897,
        "categories": 2000,
        "leaf_categories": 1600,
        "brands": 5000,
        "customer_groups": 50,
        "customer_prices": 1250416,
        "products_with_contract_price": 248613,
        "largest_leaf_products": 125288,
        "top_brand_products": 407233,
        "out_of_stock_products": 749233
      },
      "keysetMatchesOffset": true,
      "queries": {
        "Q0": {
          "p50": 0.466,
          "p95": 0.658,
          "p99": 0.737,
          "max": 0.796,
          "min": 0.327,
          "mean": 0.486,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q1": {
          "p50": 0.715,
          "p95": 1.019,
          "p99": 1.165,
          "max": 6.791,
          "min": 0.546,
          "mean": 0.772,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q2": {
          "p50": 0.858,
          "p95": 1.218,
          "p99": 1.443,
          "max": 49.027,
          "min": 0.638,
          "mean": 1.055,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset": {
          "p50": 0.69,
          "p95": 0.973,
          "p99": 1.085,
          "max": 4.772,
          "min": 0.481,
          "mean": 0.734,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_offset": {
          "p50": 4.773,
          "p95": 6.318,
          "p99": 6.886,
          "max": 9.647,
          "min": 3.48,
          "mean": 4.896,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_keyset_p2000": {
          "p50": 0.691,
          "p95": 0.984,
          "p99": 1.305,
          "max": 8.237,
          "min": 0.525,
          "mean": 0.761,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q3_offset_p2000": {
          "p50": 40.294,
          "p95": 50.592,
          "p99": 53.391,
          "max": 59.815,
          "min": 26.296,
          "mean": 39.975,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q4": {
          "p50": 16.046,
          "p95": 164.03,
          "p99": 228.827,
          "max": 271.173,
          "min": 1.804,
          "mean": 47.41,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 12.14
        },
        "Q5": {
          "p50": 102.491,
          "p95": 236.328,
          "p99": 310.161,
          "max": 425.346,
          "min": 3.911,
          "mean": 104.878,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 20
        },
        "Q6": {
          "p50": 12.558,
          "p95": 215.22,
          "p99": 504.705,
          "max": 523.554,
          "min": 0.878,
          "mean": 63.716,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 22.837
        },
        "Q6_pop": {
          "p50": 4.253,
          "p95": 81.232,
          "p99": 128.927,
          "max": 160.474,
          "min": 0.977,
          "mean": 16.911,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 22.807
        },
        "Q6_count_capped": {
          "p50": 7.576,
          "p95": 32.24,
          "p99": 58.104,
          "max": 83.446,
          "min": 0.883,
          "mean": 11.217,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 1
        },
        "Q7": {
          "p50": 0.923,
          "p95": 1.28,
          "p99": 1.389,
          "max": 2.706,
          "min": 0.678,
          "mean": 0.961,
          "iterations": 300,
          "warmup": 20,
          "rowsAvg": 24
        },
        "Q8": {
          "p50": 109.345,
          "p95": 137.335,
          "p99": 139.819,
          "max": 139.819,
          "min": 62.942,
          "mean": 109.832,
          "iterations": 20,
          "note": "batch time = BEGIN + UPDATE + COMMIT round trips; COMMIT includes WAL flush (synchronous_commit=on)",
          "updateStatementP50": 55.72,
          "commitP50": 52.895,
          "warmup": 5,
          "batchSize": 1000,
          "rowsUpdated": 20000,
          "rowsPerSecAtP50": 9145,
          "rowsPerSecOverall": 9105
        },
        "Q9": {
          "status": "derived",
          "rowsPerSec": 63741,
          "note": "products rows / seconds of generate.sql step \"products\" (in-database generation + insert, no indexes)"
        }
      }
    }
  ],
  "notes": [
    "Single client, one connection, sequential queries on the same host as the server. No concurrency or load test: numbers show how query cost scales with catalog size, not throughput under traffic.",
    "Latency is wall-clock round trip in node-postgres (performance.now()) and includes driver + Docker Desktop port forwarding. Q0 (SELECT 1) is the floor: 0.40-0.54 ms p50 across runs.",
    "Percentiles use the nearest-rank method over 300 measured iterations per read query, after 20 warm-up iterations. Parameters are drawn from the loaded data with a seeded PRNG (mulberry32, seed 20260924 + size).",
    "Connect via 127.0.0.1, not localhost: during development localhost resolved to ::1 on this Windows host and a 1,000-element array parameter took ~44 ms vs ~1 ms over 127.0.0.1 (Docker Desktop forwarding path). All published numbers use 127.0.0.1.",
    "Q3_keyset_p2000 / Q3_offset_p2000 are skipped at 10,000 products: only 9,490 active products exist, page 2,500 needs 60,000.",
    "Keyset and OFFSET returned identical rows for the first cursor at every size (keysetMatchesOffset = true).",
    "Q5 at 5,000,000: the planner combines the category index with the jsonb_path_ops GIN on attrs; a common color matches ~420k rows in the GIN scan, so p50 is 102 ms. What we would change at this size (not applied in this run): promote hot facets (color) to typed columns with a composite index, or serve facet counts from precomputed aggregates / a search engine.",
    "Q6 ranks every match with ts_rank before LIMIT 24; frequent tokens (the most common brand is ~8% of the catalog) push p95 to 215 ms at 5,000,000. Q6_pop (popularity order) and Q6_count_capped (count stops at 1,001, shown as 1000+) are measured as the cheaper alternatives.",
    "Q8 updates price_cents, which is indexed, so updates are not HOT and every row touches all product indexes including two GIN indexes. Q8 is 20 measured batches of 1,000 rows after 5 warm-up batches (not 300 iterations). At 5,000,000 COMMIT p50 rose to 53 ms (about 7 ms at smaller sizes); the run started right after the 5M bulk load, so checkpoint/WAL flush contention is the likely cause but was not isolated.",
    "Q9 (ingest) is in-database generation (hashing, string building, unaccent, to_tsvector) plus INSERT into a table without secondary indexes. It is not COPY from a file; a real ERP import is usually bound by parsing and network, not by Postgres.",
    "Data is synthetic and deterministic (hash of row id), with skewed distributions: brand ~1/k (Zipf s=1), leaf category ~u^2, popularity log-uniform, price log-uniform 1.99-4,975 EUR. Real catalogs differ; the shape of the curve matters more than any single number.",
    "The 5,000,000 dataset (2.771,6 MiB (oko 2,9 GB) with indexes) is larger than shared_buffers (1 GB); pages were served from shared_buffers and the WSL2 VM page cache. Cold-cache (disk) latency was not measured.",
    "JIT is on (default) but no captured plan shows JIT compilation.",
    "EXPLAIN (ANALYZE, BUFFERS) plans in plans/ use the first parameter set of each pool and were captured after the measured iterations (warm cache)."
  ],
  "finishedAt": "2026-09-24T11:51:02.651Z"
}
