[object Object]

HubDB handles small lookup tables effortlessly. Past 10,000 rows it gets temperamental: slow filters, broken pagination, page-render timeouts. The fix isn’t to abandon HubDB; it’s to architect for scale.

Hard limits to design around

A single HubDB table caps at 10,000 rows by default (raisable on Enterprise). Per-row size caps around 100KB. Per-portal table count caps at 200. Plan around these.

Index your filter columns

HubDB lets you mark columns as filterable. The filterable columns get an index; non-filterable ones don’t. Mark every column you’ll query against as filterable, even if you only query it occasionally.

Limit columns returned

Don’t fetch all 30 columns when you need 4. Use the select parameter:

{% set rows = hubdb_table_rows(123456, "select=name,price,sku&category=widgets") %}

Smaller payloads = faster page renders.

Paginate aggressively

For listing pages over 50 rows, paginate. Don’t ship a single page with 500 rows; mobile users will abandon and your LCP will tank.

{% set page = request.query_dict.page|int|default(1) %}
{% set rows = hubdb_table_rows(123456, "limit=20&offset=" ~ ((page - 1) * 20)) %}

Cache page output, not just data

HubSpot’s CDN caches the rendered HTML. If your HubDB table updates infrequently (weekly product list, monthly partner directory), the page will serve from cache for most visitors. Set the page’s cache control accordingly via the page settings.

Use the staged/published model

HubDB has a draft (staged) layer and a live (published) layer. Always edit the staged version, validate, then publish. A bulk import directly to live destroys the page during import.

API for bulk operations

For bulk row updates, use the API not the UI:

PUT /cms/v3/hubdb/tables/{tableId}/rows/draft/batch/upsert

The UI’s bulk import has a 2,000 row practical ceiling before timeouts. The API handles 10,000+ comfortably with proper batching.

When to leave HubDB

If you need full-text search, joins across tables, or relational integrity, you’ve outgrown HubDB. Move to a custom object (CRM-side) or a true database accessed via serverless function. Forcing HubDB into a relational role costs more than migrating.

Foreign key columns are limited

HubDB supports a foreign_id column type that joins to another HubDB table. Useful, but performance degrades at scale. For more than two-table joins, query each table separately and join in HubL.

What to do this week

Audit your largest HubDB table. Mark every column you ever filter on as filterable. Add select to your most expensive listing page. Measure LCP before and after.

[object Object]
Share