Skip to content

Truto vs Hotglue: Declarative Unified API vs Python ETL for B2B SaaS

A technical comparison of Hotglue's code-first Python ETL approach versus Truto's declarative JSONata Unified API architecture for B2B SaaS integrations.

Uday Gajavalli Uday Gajavalli · · 23 min read
Truto vs Hotglue: Declarative Unified API vs Python ETL for B2B SaaS

You are a startup product leader or engineering director staring at a pipeline of stalled deals. The pattern is obvious. Prospects evaluate your product, love the core feature set, and then ask if you natively integrate with Salesforce, Workday, NetSuite, or HubSpot. You reply that it is on the roadmap. By the time your engineering team actually ships the connector, the prospect has signed with a competitor.

Native integrations are no longer an optional feature. According to Zylo's 2026 SaaS Management Index, the average enterprise company now manages 305 SaaS applications. Interoperability is a hard requirement for enterprise procurement. If your team is still hand-rolling connectors in Python or Node, the math gets ugly fast.

If you are evaluating Truto vs Hotglue to unblock your integration roadmap without scaling an integrations engineering team, you will quickly realize these two platforms solve overlapping business problems from fundamentally different architectural layers.

Hotglue is a code-first embedded ETL (Extract, Transform, Load) platform built on Python and the Singer spec. You write transformation scripts for each integration to move bulk data. Truto is a declarative Unified API platform. It normalizes third-party APIs using JSONata and JSON configurations, featuring a real-time proxy that reads and writes data through one generic execution path without requiring a single line of integration-specific code.

This guide strips away the marketing copy to examine the raw engineering trade-offs between imperative Python scripts and declarative JSON configurations, infrastructure handling, and long-term maintenance burdens.

The Core Architectural Difference: ETL Pipeline vs Unified Proxy

Before comparing specific features, we must define the architectural divide. Buying the wrong tool category will force your engineering team into months of painful workarounds.

Short answer: Hotglue is a pipeline. Truto is a proxy.

What is an Embedded ETL (Hotglue)? Embedded ETL platforms are designed for batch data synchronization. The system connects to a third-party API, extracts massive volumes of data (often millions of rows), runs that data through a transformation layer, and loads it into your application's database or data warehouse. The job is the unit of work. Hotglue jobs traditionally go through each step of the ETL pipeline: extract raw data from a source connector, use the Python layer to process the data, and then write the final data to a target.

What is a Declarative Unified API (Truto)? A Unified API acts as a real-time proxy layer sitting directly between your application and hundreds of third-party SaaS platforms. Instead of syncing bulk data into your database on a schedule, your application makes a standard REST request to the Unified API. The platform translates the request, authenticates it, maps the data model, and forwards it to the upstream provider in real time. No background job. No warehouse round-trip.

flowchart LR
    subgraph Hotglue["Hotglue: ETL Pipeline"]
        A1[Source Connector<br>Singer Tap] --> A2[Python Transform<br>Pandas / Dask]
        A2 --> A3[Target<br>Warehouse / DB / API]
    end
    subgraph Truto["Truto: Real-Time Proxy"]
        B1[Your App] -->|Unified API call| B2[Generic Engine]
        B2 -->|JSON config + JSONata| B3[Provider API]
        B3 -->|Normalized response| B1
    end

This is not a cosmetic difference. It dictates how each platform handles latency, bidirectional writes, custom fields, error semantics, and operational debugging. For a deeper look at this category, see our embedded iPaaS vs unified API guide.

Hotglue: Code-First Python ETL for Bulk Data

Hotglue positions itself as an embedded ETL platform designed to move bulk data to a warehouse or database. It offers a library of over 600 open-source connectors out of the box and natively supports all Singer spec and Airbyte YAML connectors. The connection UX is similar to most embedded platforms—a widget your end users click through to authorize their accounts.

What happens after the authorization handshake is where the architecture shows itself.

How the Python Transformation Layer Works

Hotglue's defining characteristic is its reliance on Python. Hotglue lets developers leverage the Python ecosystem to compose transformation scripts, combining Python modules like Pandas and Dask inside a JupyterLab workspace.

For every integration you enable, your developers must write, deploy, and maintain Python scripts to fit the raw API data to your system's schema. If you want to pull contacts from HubSpot and Salesforce, you write two distinct Python scripts. A conceptual workflow looks like this:

# Conceptual representation of a Python ETL transform script
import pandas as pd
 
def transform_salesforce_contacts(raw_data):
    df = pd.DataFrame(raw_data)
    # Manually map fields
    df['first_name'] = df['FirstName']
    df['last_name'] = df['LastName']
    # Handle custom fields explicitly via code
    df['industry'] = df.get('Custom_Industry__c', None)
    return df.to_dict('records')

Where Hotglue's Model Shines

  • Bulk historical loads: If you're pulling years of HubSpot deals into BigQuery for analytics, an ETL pipeline is the right shape.
  • Reverse ETL into customer warehouses: Writing flat tables to Snowflake or Postgres is a first-class use case.
  • Heavy data manipulation: Pandas and Dask exist for a reason. If your transform involves complex mathematical aggregations, fuzzy matching, or natural language processing on text fields before saving to your database, Python is a better language for that than a declarative expression.
  • Open source flexibility: All Hotglue connectors are open source and based on the Singer spec, with hundreds of taps available. If a connector doesn't exist, you can create a new Singer tap yourself using the Singer SDK rather than waiting on a vendor's roadmap.

Where the Model Creates Friction

The same flexibility shows up as massive maintenance overhead. APIs are chaotic. Providers deprecate endpoints, change pagination limits, and alter payload structures. Every transform is code you wrote. When the provider's API changes a field name, or when a customer wants slightly different mapping, those changes happen in Python, not config.

If you support 50 integrations, your engineering team is actively maintaining 50 distinct Python codebases. This approach scales linearly with headcount. You will eventually need a dedicated integrations team just to keep the scripts running.

There is also a latency floor. ETL pipelines are scheduled or triggered. They are not the right primitive for the moment your user clicks "Create Deal" in your UI and expects it to appear in their CRM in under a second. Hotglue's streaming jobs do the extract and load concurrently, but the model is still job-shaped, not request-shaped.

Truto: Declarative JSONata for Real-Time API Access

Truto takes the opposite stance: there should be zero integration-specific code in the platform. The architecture is built on a single generic execution pipeline that reads declarative JSON configurations.

Zero Integration-Specific Code

In Truto, every connector is described entirely as JSON configuration and JSONata mapping expressions. JSONata is a lightweight, functional query and transformation language for JSON data. Whether you are querying a REST API, a SOAP wrapper, or a GraphQL endpoint, the underlying execution engine runs the exact same code path.

When you request a unified Contact resource, Truto reads the configuration for the specific provider, applies the JSONata transformation to the request, fetches the data, and applies a reverse JSONata transformation to the response.

Here is a stripped-down example of what a unified field mapping looks like:

{
  "resource": "contact",
  "provider": "hubspot",
  "endpoint": "/crm/v3/objects/contacts",
  "method": "GET",
  "response_mapping": {
    "id": "properties.hs_object_id",
    "email": "properties.email",
    "first_name": "properties.firstname",
    "last_name": "properties.lastname",
    "created_at": "$toMillis(createdAt)"
  }
}

The same pipeline handles Salesforce by reading a Salesforce config. Same code path. Different JSON. Adding a new connector is a data-only operation—you ship config, not code. We wrote about this pattern in detail in our deep dive on zero integration-specific code.

Unlike older competitors such as Merge.dev—which force data into rigid, standardized models that often strip out custom fields—Truto's dynamic mapping engine handles enterprise edge cases cleanly. If an enterprise customer has a highly specific custom object in their Salesforce instance, you can map it dynamically. Read more in our guide on why unified data models break on custom Salesforce objects.

The Proxy Architecture and Data Residency

Because Truto operates as a proxy, it does not store your customer's third-party payload data at rest. This drastically reduces your compliance surface area for SOC 2, HIPAA, and GDPR.

The declarative approach extends to harder cases: Truto's proxy converts GraphQL-backed integrations like Linear into REST CRUD resources using placeholder-driven request templates, so callers get the same GET /tickets interface regardless of whether the upstream is REST or GraphQL.

Truto also supports passthrough access. If a unified endpoint doesn't cover a niche field, you can hit the raw provider API through Truto's proxy with the OAuth credentials already managed for you. No re-authentication. No SDK shim.

The Trade-off, Honestly Stated

Declarative configurations are not a free lunch. JSONata is more constrained than Python. If your transform genuinely needs to call out to a vector database, run a regression model, or join data across three providers in one step, a declarative engine is the wrong tool. Most B2B SaaS integrations don't need that. Some do. Pick accordingly.

Both platforms provide a drop-in frontend component so your customers can authorize their SaaS accounts without leaving your product. The shape of that component is where the platforms diverge.

Truto Link SDK is a JavaScript SDK that opens a popup connection flow driven by a short-lived link token. Your backend mints the token, your frontend calls authenticate(linkToken) which opens a new window with the Truto Link UI and returns a promise that resolves after your customer has successfully connected their account. That's the entire integration surface: one function call in, one connected account out.

Hotglue widget (v3) is a React and JavaScript component set that mounts inside your app. The hotglue widget is a white-labeled JavaScript component set for your users to link to hotglue integrations, without leaving your app. Beyond the OAuth handoff, it also renders in-widget UI for source management, sync history, custom field mapping tabs, and buttons to trigger jobs. It is designed to be the primary place your customers manage integrations after authorization, not just authorize them.

The difference is philosophical:

  • Truto Link is a connection primitive. It hands off a connected account to your app; everything downstream (data reads, writes, mapping controls, sync configuration) happens through your own UI calling the Truto REST API.
  • Hotglue's widget is a self-serve integrations control panel that lives inside your product and exposes job-shaped controls to your end user.

If you want tight control over the post-connection surface - a native settings page, a bespoke field-mapping UI, your own sync scheduler - a thin connection SDK is the right primitive. If you want to ship an integrations experience without building any UI yourself, an embedded control panel gets you there faster, at the cost of design and UX flexibility.

A short comparison of the two connection UIs:

Dimension Truto Link SDK Hotglue Widget (v3)
Distribution @truto/truto-link-sdk npm package @hotglue/widget React package + widgetv2.js script tag
Surface area Popup connection flow Inline React/JS component with tabs
Session model Short-lived link token minted server-side API key + envId + tenant ID mounted in a HoC provider
Post-connection UI You build it against Truto's REST API Built into the widget (sync history, mappings, schedules)
Return value Promise resolving with { result, integration } Event listeners + client-side helper functions
Primary use case Real-time, bidirectional product integrations Self-serve ETL configuration in your app

On screenshots and GIFs: Because both widgets are white-labeled and render inside your app, the actual visual is dominated by your brand. Screenshots of vanilla widgets are less useful than a working proof of concept - both vendors will pair with you to record a short flow against your real UI during a trial.

Customization and Theming Examples

Both widgets support white-label branding, but the customization surface differs significantly.

Hotglue widget customization. Developers can embed the component in either React, JavaScript, or NextJS inside their webapp, with the ability to customize the CSS of the component and make it look completely native. The widget also ships a light theme with a white background by default, with a toggle that displays a dark widget instead. Localization is a first-class concern: widget and connection behavior can be defined by passing values directly in your frontend code, including tenant metadata, dynamic OAuth parameters, and localization text. Post-connection tabs (custom mapping, filters, sync schedule, run-job) are opt-in per environment.

Truto Link SDK customization. Because the surface is a popup rather than a full control panel, there is less UI to style, and the customization surface is intentionally small: embed the Truto link SDK in your app to handle the connection flow, OAuth, API credentials, and customize it to match your brand colors. Brand colors, logo, and copy are configured at the environment or link-token level so every popup opens with your product's branding applied. Accessibility follows standard web patterns - the popup is a focus-trapped modal with keyboard navigation, and localized copy is configured server-side rather than passed at mount time.

The practical tradeoff at a glance:

Customization dimension Hotglue widget Truto Link SDK
Component styling CSS overrides on the React/JS component Brand colors, logo, and copy via configuration
Dark mode Built-in toggle Themed via environment configuration
Localization Text-string overrides at mount time Configurable copy per environment/token
Post-connection UI Custom mapping, sync schedule, filters in-widget Not part of the widget - build in your own UI
Font and design system Inherits page CSS via className overrides Popup inherits configured theme
Accessibility Standard React accessibility patterns Focus-trapped modal, keyboard navigable

If your product's design system is strict and every pixel must match, both widgets get close. Hotglue gives you a larger, more configurable UI surface if you want in-widget functionality without building it yourself. Truto's smaller surface means less to style and less to visually diverge from your app.

Sample Embed Code and Configuration

Here is what an embed looks like in each platform, side by side.

Hotglue widget (React):

import HotglueConfig, { useHotglue } from '@hotglue/widget'
 
function App() {
  return (
    <HotglueConfig config={{
      apiKey: 'your-public-environment-api-key',
      envId: 'your-env-id',
    }}>
      <ConnectButton />
    </HotglueConfig>
  )
}
 
function ConnectButton() {
  const { openWidget, link } = useHotglue()
  return (
    <>
      {/* Opens the full Connections panel for the tenant */}
      <button onClick={() => openWidget('tenant-123')}>
        Manage integrations
      </button>
      {/* Jumps straight to a specific connector's OAuth popup */}
      <button onClick={() => link('tenant-123', 'flow-id', 'salesforce')}>
        Connect Salesforce
      </button>
    </>
  )
}

The HotglueConfig provider wraps your app with the API key and env ID, and the useHotglue hook exposes openWidget to launch the widget for a given tenant. A plain HTML/JS variant is also available via a <script> tag that calls HotGlue.mount({ api_key, env_id }) and then HotGlue.open(tenantId) or HotGlue.link(tenantId, flowId, connectorId).

Truto Link SDK:

import authenticate from '@truto/truto-link-sdk'
 
async function connectIntegration(integrationSlug) {
  // 1. Mint a short-lived link token on your backend.
  //    Never expose your Truto API key to the browser.
  const { link_token } = await fetch('/api/truto/link-token', {
    method: 'POST',
    body: JSON.stringify({
      tenant_id: 'tenant-123',
      integration: integrationSlug,
    }),
  }).then(r => r.json())
 
  // 2. Open the Truto Link popup.
  try {
    const result = await authenticate(link_token)
    // result: { result: 'success', integration: 'salesforce', ... }
    await fetch('/api/integrations/connected', {
      method: 'POST',
      body: JSON.stringify(result),
    })
  } catch (err) {
    // User closed the popup or auth failed
  }
}

The backend endpoint that mints the token attaches your tenant identifier, the target integration, per-tenant scopes, and any mapping overrides you want scoped to that account. After authenticate resolves, your app owns the connected account and makes unified API calls against it - no widget lifecycle to manage, no in-app tabs to keep rendered.

Notice the shape difference: Hotglue mounts a persistent widget provider at the top of your React tree and exposes an in-widget UX; Truto opens a popup on demand, returns an account ID, and gets out of the way.

Post-Connection UX Differences for End Users

This is where the ETL-vs-proxy split becomes visible to the person using your product.

With Hotglue, once a customer has linked a source, the widget-native experience is job-shaped. Depending on which widget settings you enable per environment, users can unlink and re-configure credentials, run a new sync job, modify the sync schedule, and modify the field map of what data they want to import from a specific integration. When they click "sync now", a job runs in the background, extracts data from the third-party API, applies your Python transform, and lands it in your target. Data becomes available to your app after the job completes - minutes for small syncs, longer for historical loads. Duplicate handling on a full re-sync is your responsibility in either the transform script or the target.

With Truto, there is no post-connection widget by default. After authenticate resolves, your app immediately holds a connected account it can call. A user creating a deal in your UI translates into a POST /unified/crm/deals in the same request-response cycle - the record appears in the customer's CRM before the user's spinner finishes. Reads work the same way: GET /unified/crm/contacts returns live data from the upstream provider on every call, with no staleness window.

The behavioral difference for the end user:

Post-connection action Hotglue (ETL) Truto (proxy)
"Create a deal in Salesforce" Requires a bi-directional flow / target and a job cycle Unified API POST, sub-second, in the same request
"See my latest contacts" Data as of last sync (minutes to hours old) Live pull from provider on each request
"Change what fields I sync" In-widget custom mapping tab Configured server-side via mapping overrides
"Reconnect an expired OAuth token" Reconnect flow inside the widget Re-open Link SDK popup for the same integration
"Trigger a full backfill" Manual re-run job button in widget Sync job kicked off from your app via API
"Custom field on their Salesforce instance" New branch in the Python transform + redeploy JSONata override on that connected account

If your product needs the "click to create in the customer's CRM" experience inside a real-time workflow, the proxy model is the shape you want. If your product needs to ingest years of historical data into a warehouse and analyze it, the job-shaped model is a better fit.

Handling Infrastructure: Rate Limits, Webhooks, and Auth

Any senior engineer evaluating integration platforms will immediately ask about edge cases. This is where the architectures diverge in ways that matter on-call.

The Brutal Reality of Rate Limits

Many integration platforms claim to "magically handle" rate limits by absorbing HTTP 429 (Too Many Requests) errors and queuing requests internally. This is an architectural anti-pattern for real-time systems. If a unified API absorbs a 429 error and holds the request for 15 minutes, your application's user interface will hang, leaving your end-user staring at a loading spinner with no context.

Truto takes a radically transparent approach. We do not retry, throttle, or apply backoff on rate limit errors. When an upstream API returns an HTTP 429, Truto passes that exact error back to the caller immediately.

To make this actionable, Truto normalizes the upstream rate limit information into standardized IETF headers, regardless of how the third-party provider formats them:

  • ratelimit-limit: The maximum number of requests permitted in the current window.
  • ratelimit-remaining: The number of requests remaining in the current window.
  • ratelimit-reset: The exact timestamp when the rate limit window resets.

By passing these headers directly to your application, your backend can implement intelligent exponential backoff, update your database state, and show the end-user an accurate message (e.g., "Salesforce rate limit exceeded. Try again in 45 seconds"). For deeper coverage, see our piece on handling API rate limits across third-party APIs.

Webhook Ingestion and Normalization

Polling APIs for changes is inefficient and expensive. Both platforms offer webhook support, but the execution differs.

Truto supports two inbound webhook ingestion patterns: account-specific webhooks tied to a single connected account, and environment-integration fan-out webhooks that fan out a single provider event to many tenants. When a provider sends an event (like a new ticket in Zendesk), Truto catches the payload, verifies the provider's signature, and uses JSONata to normalize the event into a standard format.

For outbound delivery to your application, Truto utilizes a highly reliable queue and object-storage claim-check pattern. We deliver the normalized event to your webhook endpoint with a cryptographic signature (X-Truto-Signature). Your backend verifies this signature to guarantee the payload originated from Truto and was not tampered with in transit. This decoupled architecture ensures massive spikes in third-party events do not overwhelm your servers.

Hotglue exposes webhook events for job status (sync started, succeeded, failed) and supports trigger-based workflows, but the primitive is still job-centric rather than real-time event-centric.

OAuth Lifecycle Management

Truto refreshes OAuth tokens ahead of expiry so your in-flight requests don't fail because a refresh token rotated three seconds before the call. The platform schedules work ahead of token expiry. Hotglue handles concerns like ETL dependency caching and Python virtual environment initialization, but manages credentials inside the job runner.

Maintenance at Scale: Scripts vs Configurations

The true cost of an integration platform is rarely the subscription price. The true cost is the engineering hours spent maintaining the connections over a three-year horizon. We explored this extensively in our Truto vs Hotglue declarative JSON vs code-first Python guide.

The Technical Debt of Python Scripts

If you choose a code-first ETL approach, you are taking ownership of the transformation logic. When an API provider releases a breaking change—such as renaming a field from customer_id to customerId—your scheduled Python script will fail.

Your engineering team must:

  1. Triage the failed batch job.
  2. Read the provider's updated API documentation.
  3. Modify the Python script.
  4. Write new unit tests for the script.
  5. Deploy the updated script to the ETL platform.
  6. Manually trigger a historical backfill to recover the missed data.

When you scale to 50 or 100 integrations, this maintenance cycle becomes a full-time job for multiple engineers. The flexibility of Python becomes a massive liability.

The Leverage of Declarative Configurations

Declarative architectures shift the maintenance burden away from your codebase. With Truto, the JSONata configurations are managed centrally. When an API provider introduces a breaking change, Truto updates the underlying configuration mapping.

Your engineering team does not write new code. You do not deploy new services. The next time your application makes a request to the Truto proxy, the new JSONata mapping executes automatically.

This matters immensely when you start running per-customer overrides. Truto supports a 3-level override hierarchy (global → integration → connected account) for field mappings. You can customize a unified data model for a single enterprise customer without forking a connector. We covered the pattern in detail in Per-Customer API Mappings.

Quick Reference: JSONata Examples and Common Patterns

When you need an integration platform that lets you configure field mappings per customer without forking code, JSONata gives you a compact declarative language for describing the shape of the output. Here are the patterns that come up most often in production integrations.

Simple field rename and type coercion:

response.{
  "id": $string(Id),
  "first_name": FirstName,
  "last_name": LastName,
  "created_at": CreatedDate
}

Customer-specific custom fields:

Suppose one enterprise tenant tracks a Preferred_Region__c custom field in Salesforce. You override the base response mapping on their integrated account without touching the platform-level config:

response.{
  "preferred_region": Preferred_Region__c,
  "custom_fields": $sift($, function($v, $k) { $k ~> /__c$/i })
}

The override is deep-merged on top of the base mapping, so every other field on that resource continues to work untouched. This is the exact primitive that answers the customer-specific integration platform question: mappings are data attached to a single connected account, not a fork of the connector.

Conditional logic and defaults:

response.{
  "status": is_active ? "active" : "inactive",
  "email": $firstNonEmpty(work_email, personal_email),
  "tags": $map(labels, function($v) { $v.name })
}

Query translation for provider-specific filters:

{
  "page_size": query.limit ? $number(query.limit) : 100,
  "after": query.next_cursor,
  "filter": query.updated_after
    ? "updated_at gt " & query.updated_after
}

Multi-value mapping (e.g., phone number types):

"phone_numbers": $filter([
  { "number": Phone, "type": "work" },
  { "number": MobilePhone, "type": "mobile" },
  { "number": HomePhone, "type": "home" }
], function($v) { $v.number })

Every expression above is stored as data in a config field, not compiled into a binary. You can hot-swap it per environment or per connected account without redeploying anything.

Operational Notes: Validation, Versioning, and Promotion

Declarative per-customer mappings are only useful if you can operate them safely. A few practical constraints and workflows to know.

Three-level override hierarchy. Truto resolves the final mapping by deep-merging three layers in order: platform base → environment override → account override. Individual fields (response mapping, query mapping, resource, method, before/after steps) can each be overridden independently. You do not have to copy the entire mapping to change one field.

Validation. JSONata expressions are compiled at request time. If an expression is syntactically invalid or throws during evaluation, the request fails with a structured error rather than silently dropping data. For sync jobs, evaluation errors surface on the run with the specific expression that broke, so you can fix and re-run without a code deploy.

Versioning. Integration configs and unified model definitions use optimistic concurrency—every update includes the current version number and the platform rejects stale writes. Previous versions are retained for audit and rollback, so you can revert a bad mapping change quickly.

Environment promotion. Environment-level overrides are scoped to a single environment (staging, production, per-region). You can test a mapping change in staging against real tenant data, then promote it to production by copying the override JSON. No build step, no code review pipeline unless you choose to add one.

Account-level scoping. Account overrides live on the connected account record and only affect that specific tenant's traffic. A misconfigured override for one customer cannot break the mapping for anyone else. This is the primitive that lets you say "yes" to enterprise customers with unusual data models without forking your integration code.

No hard limits on override count. You can attach overrides to every connected account if you need to. Each override is a JSON blob, so storage cost is negligible and there is no per-account config ceiling to design around.

Sensitive fields stay encrypted. Credentials referenced in mappings (OAuth tokens, API keys, tenant subdomains) are encrypted at rest and never exposed in list responses. Mapping expressions read from the account context at evaluation time.

Comparison: Truto Declarative Mapping vs iPaaS vs Code-First SDKs

Three architectural patterns dominate the market. Each solves a different problem, and the right choice depends on where field mapping happens in your organization.

Dimension Declarative Unified API (Truto) iPaaS / Embedded ETL (Hotglue, Workato, Tray) Code-First SDK (SDK-per-connector platforms)
Field mapping definition JSONata expression in JSON config Python or visual workflow builder TypeScript / language SDK
Per-customer customization Account-level override on existing config Fork the workflow, redeploy per tenant Fork connector code, redeploy
Deploy required for a mapping change? No Yes (workflow republish or Python push) Yes (SDK release + client upgrade)
Custom fields for enterprise accounts JSONata expression targeting the field New Python transform branch New SDK type + code path
Rollback Revert config version Redeploy previous workflow Redeploy previous SDK version
Testing surface Expression + evaluation context Full pipeline test with fixtures Unit tests + integration tests
Skill required to change a mapping JSONata (functional expression language) Python, Pandas, workflow tooling Full engineering stack
Data at rest None (proxy) Intermediate stored during pipeline Depends on SDK design
Time to first mapping change Minutes Hours to days Days to weeks
Who can change a mapping Solutions engineering, support Data engineers Backend engineers only

The tradeoff is expressiveness. Code-first SDKs give you unrestricted access to any library or database. iPaaS platforms give you visual composability and heavy transform primitives. Declarative mappings give you speed and operational simplicity at the cost of some flexibility on complex transforms.

When to Choose Declarative Per-Customer Mapping

Not every product needs per-customer mapping. A few questions to ask before committing to a pattern.

Choose declarative per-customer mapping if:

  • You sell to enterprise customers who run non-standard object models (custom Salesforce objects, HubSpot pipelines, NetSuite subsidiaries).
  • Your support team routinely receives requests like "can you sync our Preferred_Region__c field?" and you want to answer yes without a release.
  • You want solutions engineering or customer success to configure mappings, not backend engineers.
  • Real-time, bidirectional API access matters more than heavy in-flight transforms.
  • Your integrations roadmap is growing faster than your integrations headcount.
  • You need audit trails, versioned rollbacks, and per-environment promotion without building your own release pipeline for integration code.

Stick with code-first if:

  • Your transforms genuinely require Python libraries, ML models, or cross-provider joins that a functional expression language cannot express.
  • You have a mature integrations team that already owns dozens of connectors in code and the cost of migration outweighs ongoing maintenance.
  • Your integration surface is small (three to five connectors) and stable.

Stick with iPaaS if:

  • The primary consumer of the integration is a data warehouse or analytics layer, not a real-time product surface.
  • You need visual workflow authoring for non-engineers.
  • Bulk historical loads dominate your workload.

The Truto vs Hotglue Product Comparison Matrix

Dimension Hotglue Truto
Architecture Embedded ETL pipeline Real-time Unified API proxy
Integration definition Python scripts + Singer/Airbyte taps Declarative JSON + JSONata
Primary use case Bulk data extraction into warehouse / DB Real-time bidirectional reads & writes
Connector library 600+ open-source Singer/Airbyte connectors 100+ first-party connectors with passthrough
Embeddable UI React/JS widget with in-widget sync UX Popup Link SDK returning a connected account
Custom field handling Custom Python in transform script JSONata expression or passthrough endpoint
Latency profile Job-scheduled (minutes to hours) Per-request (sub-second proxy)
New connector shipping Write a Singer tap + Python transform Add a JSON config (no code deploy)
Rate-limit handling Job retries within ETL flow 429 passed to caller with IETF headers
Webhooks Job status webhooks + real-time triggers Provider event normalization + signed outbound delivery
Data residency Processed in cloud environment, not stored Pass-through proxy with zero data at rest
Best fit team Teams comfortable owning Python pipelines Teams that want config-only integration ops

Which Platform Should You Choose?

The decision between Truto and Hotglue is not about which tool has more features. It is a fundamental choice about software architecture and data latency.

You should choose Hotglue if:

  • Your dominant use case is bulk data movement into a warehouse or analytics layer.
  • You require massive historical data extraction (ETL) on a scheduled basis.
  • Your team is comfortable owning Python transformation code per connector.
  • You need the long tail of open-source Singer/Airbyte taps and are happy to fork them.
  • Your customer-facing SLAs are measured in hours, not seconds.

You should choose Truto if:

  • Your product is a transactional B2B SaaS application requiring real-time, bidirectional API access inside customer-facing workflows.
  • You want zero integration-specific code so adding a connector is a data-only operation.
  • You want to avoid the compliance risks of storing third-party data at rest.
  • You serve enterprise customers with custom fields and require per-tenant mapping overrides.
  • You need standardized rate limit headers to build resilient, user-facing error handling.
  • You'd rather your engineers ship core product features than maintain a fleet of ETL scripts.

There is no architecturally pure answer. Some teams genuinely need both—a Unified API for the in-product experience and an ETL pipeline for the data team's warehouse. If you find yourself in that camp, the question isn't "which one," it's "which one is on the critical path of your roadmap right now."

Stop losing enterprise deals because your native integration roadmap is moving too slowly. By adopting a declarative Unified API, you can treat integrations as configuration rather than code.

Next Steps

If your sales team is losing deals over missing integrations, the right move is to run a 14-day proof of concept against your two most-requested connectors. Measure three things: how long it takes to ship the first integration, how long it takes to ship the tenth, and how long it takes to add a custom field for a single customer without redeploying. That last metric is where declarative architectures separate from code-first platforms.

FAQ

What is the main difference between Truto and Hotglue?
Hotglue is an embedded ETL platform that uses scheduled Python scripts and Singer/Airbyte taps to extract bulk data into a database. Truto is a declarative Unified API that acts as a real-time proxy, using JSONata to normalize API requests without requiring custom code.
Is Hotglue better for bulk data or real-time integrations?
Hotglue is purpose-built for bulk data movement. Its pipeline model (extract, Python transform, load) fits warehouse syncs and historical loads, but it is not the right primitive for sub-second, per-request workflows inside a customer-facing UI.
How does Truto handle API rate limits?
Truto does not absorb 429s or silently retry them. When an upstream provider returns HTTP 429, Truto passes the error directly to the caller and normalizes upstream rate-limit information into standard IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset) so your application can handle backoff accurately.
How do Unified APIs handle custom enterprise fields?
While older unified APIs often strip out custom fields to fit rigid data models, Truto uses a flexible JSONata mapping layer. This allows you to dynamically map and access custom enterprise data structures, and even apply per-customer overrides without deploying new code.
Which platform is easier to maintain at scale?
Hotglue gives you full Python control per connector, which means maximum flexibility but a growing surface of scripts to maintain. Truto's declarative model trades some flexibility for much lower long-term maintenance, since most changes are simple JSON edits rather than code deploys.

More from our Blog