
While building internal automations in HubSpot, I ran into a hard limit.
At Gadget, we manage a growing partner program. Franco, our Head of Partnerships, was manually tracking referrals in a sprawling spreadsheet — making sure each deal was properly attributed to the right partner account. As you can imagine, starting every day in spreadsheet triage mode wasn’t scalable.
The obvious answer? Track partner relationships inside the CRM itself. After all, CRM stands for Customer Relationship Management.
But then we hit a wall.
In This Content
The HubSpot Object Limit Problem
By default, HubSpot gives you two core objects: Contacts and Companies. We needed an additional custom object to properly model partner relationships.
Turns out, unlocking even one more object required upgrading to a significantly more expensive plan. The price jump? Pure sticker shock.
That’s when the question shifted from:
“What plan do we need?”
to
“Why not build this ourselves in Gadget?”
And that idea quickly evolved into something bigger:
What if this wasn’t just a workaround for us — but a plug-and-play template other HubSpot users could deploy to avoid expensive upgrades?
That’s how the HubSpot Static Object template was born.
What This Template Helps You Do
This approach lets you:
-
Avoid costly plan upgrades
-
Build your own custom automations
-
Keep control of your data — even if you downgrade your HubSpot plan
Instead of paying to unlock a custom object inside HubSpot, you externalize the object into Gadget — while still using HubSpot as your primary interface.
The Architecture: HubSpot + Gadget
This template was built from our internal use case and refined for others facing similar limitations.
Here’s how it works under the hood:
1. Postgres-Backed Models in Gadget
Gadget rapidly provisions a Postgres database and generates CRUD APIs automatically. When you define a model, you instantly get:
-
A Postgres table
-
Create, Read, Update, Delete operations
-
Environment configuration
-
Authentication scaffolding
No boilerplate required.
2. Node as the Orchestration Layer
On top of Gadget’s data model, Node handles HubSpot-specific workflows such as:
-
JWT validation
-
Conditional business logic
-
Coordinated read/write operations between HubSpot and Gadget
This keeps complex integration logic outside of HubSpot while still allowing HubSpot to act as the system of record and primary user interface.
The Use Case: Teams Within a Company
One common issue in HubSpot is distinguishing multiple groups under the same company.
For example:
-
Two separate customers under the same domain
-
Multiple departments under one company account
HubSpot doesn’t make it easy to represent structured sub-groups without creating awkward workarounds or duplicating company objects.
This template solves that by creating a custom Team object managed externally in Gadget.
Defining the Custom Object
The core model lives in:
It includes:
-
teamName – Name of the team
-
teamContacts – Array of HubSpot contact IDs
-
parentCompany – HubSpot company ID
-
portalId – HubSpot portal/account ID
These fields allow you to:
-
Define teams clearly
-
Associate multiple contacts with each team
-
Link everything back to the correct company and portal
When this model is created, Gadget automatically provisions the database table and CRUD operations.
The API Layer
The template exposes the custom object to HubSpot through a set of Node-based API routes that coordinate requests between HubSpot and Gadget.
Primary routes:
-
api/routes/hubspot/GET-teams.ts -
api/routes/hubspot/POST-action.ts
These routes:
-
Read, create, and update team records
-
Translate HubSpot identifiers into internal data models
-
Apply business logic conditionally
-
Keep workflows organized outside HubSpot
All route access is secured using JWT-based authentication.
Secure Authentication
Authentication follows HubSpot’s v3 specification and is handled in:
This route:
-
Extracts the Bearer token from the Authorization header
-
Verifies the JWT using
GADGET_ENVIRONMENT_JWT_SIGNING_KEY -
Confirms the session exists and is within a 10-minute validity window
-
Throws an error if validation fails
This ensures that communication between HubSpot and Gadget remains secure and compliant.
Why This Approach Matters
By externalizing custom objects into Gadget, you:
-
Regain control of your data model
-
Avoid long-term subscription lock-in
-
Build automations on your own terms
-
Keep HubSpot as your relationship system of record
If you’ve ever hit the same “object limit” wall, this approach offers a practical, extensible way forward.
Instead of paying more to unlock flexibility, you build it yourself — and keep it.
If you’d like, I can also create:
-
A more SEO-optimized version
-
A punchier LinkedIn post version
-
Or a highly technical deep-dive version for developers