FFastero

Connect any database. Ask in plain English.

Try free
Back to blog

Blog article

How to Set Up Reverse ETL Without Hightouch or Census

Hightouch and Census charge $10k+/year to push data from your warehouse to SaaS tools. If you have a database and a few syncs to run, you don't need either. Here's how to set up reverse ETL with SQL and a sync schedule in under an hour.

Fastero Dev TeamFastero Dev Team
2026-08-05
reverse-etlsalesforcedata-syncsql
How to Set Up Reverse ETL Without Hightouch or Census

Reverse ETL is a $400/month problem dressed up as an enterprise platform. The idea is simple: your database has data that your SaaS tools need. Lead scores belong in Salesforce. Customer segments belong in your ad platform. Enriched fields belong in HubSpot. The data flows from your analytical layer back into operational tools — the reverse of the extract-transform-load pipeline that got it there in the first place.

Hightouch and Census built a category around this. They're good products. They also start at $350/month on paper and land closer to $800-1,200/month once you add the destinations and row volumes a real team needs. At scale — 10+ syncs, multiple destinations, millions of rows — they earn that price. But most teams don't have 10 syncs. They have three. Maybe five. And they're paying enterprise rates for what amounts to a scheduled SQL query and an API call.

The other catch: both require a warehouse. Snowflake, BigQuery, Redshift, or Databricks. If your data lives in Postgres or MySQL — which it does for most startups under 100 employees — you need to first replicate your production database into a warehouse before you can reverse-ETL it back out. That's a Rube Goldberg machine.

What you actually need

Strip away the platform chrome and reverse ETL is three things:

  1. A source query — SQL that selects the rows and columns you want to push.
  2. A destination mapping — which query columns map to which fields in Salesforce, HubSpot, or wherever.
  3. A schedule — how often the sync runs.

That's it. Everything else — the drag-and-drop field mapper, the audience builder, the "model" abstraction — is UI around those three primitives. If you can write SQL, you already have the hard part.

Setting it up with Fastero

Fastero's reverse ETL works directly against your database — Postgres, MySQL, BigQuery, Snowflake, whatever you've connected. No warehouse requirement. You write the query, map the fields, set a schedule. The sync runs on Bulk API v2 for Salesforce destinations (so you're not burning through REST API limits record by record) and batched upserts for HubSpot.

Here's the walkthrough for the three most common reverse ETL use cases.

Use case 1: Push lead scores to Salesforce

Your analytics table has a computed lead score. Your reps can't see it because it lives in Postgres, not Salesforce. This is the canonical reverse ETL problem.

Step 1 — Write the source query:

SELECT
    email,
    lead_score,
    score_bucket,
    last_product_activity_at,
    trial_days_remaining
FROM analytics.lead_scores
WHERE updated_at >= NOW() - INTERVAL '1 day'
  AND lead_score IS NOT NULL
ORDER BY lead_score DESC

The WHERE updated_at >= NOW() - INTERVAL '1 day' clause makes this incremental. You're only syncing rows that changed since yesterday, not re-pushing your entire lead table. This matters for Salesforce API limits — even with Bulk API, pushing 50,000 unchanged rows daily is waste.

Step 2 — Map to Salesforce fields:

Query column Salesforce field Notes
email Email Match key (external ID for upsert)
lead_score Lead_Score__c Custom number field
score_bucket Score_Tier__c Must match picklist values exactly
last_product_activity_at Last_Product_Activity__c Custom datetime field
trial_days_remaining Trial_Days_Remaining__c Custom number field

One thing that bites people: score_bucket needs to output values that exactly match the Salesforce picklist. If your query returns "high" and the picklist expects "High", the row fails silently. Handle this in the SQL:

SELECT
    email,
    lead_score,
    INITCAP(score_bucket) AS score_bucket,  -- 'high' -> 'High'
    last_product_activity_at,
    trial_days_remaining
FROM analytics.lead_scores
WHERE updated_at >= NOW() - INTERVAL '1 day'
  AND lead_score IS NOT NULL

Step 3 — Set the schedule. Daily is right for most lead scoring models. If your scoring runs hourly, sync hourly. Match the sync cadence to how often the source data actually changes — syncing more frequently than that just burns API quota.

Use case 2: Sync customer segments to HubSpot

You've built segments in your database — churning customers, expansion candidates, users who hit a usage threshold. HubSpot needs those segments as contact properties or list memberships so marketing can target them.

SELECT
    u.email,
    CASE
        WHEN s.mrr > 500 AND s.usage_growth_pct > 20
            THEN 'expansion_candidate'
        WHEN s.last_login_at < NOW() - INTERVAL '30 days'
            THEN 'at_risk'
        WHEN s.trial_end_at BETWEEN NOW() AND NOW() + INTERVAL '7 days'
            THEN 'trial_ending_soon'
        WHEN s.mrr > 0 AND s.support_tickets_30d > 5
            THEN 'high_touch_needed'
        ELSE 'healthy'
    END AS customer_segment,
    s.mrr,
    s.last_login_at,
    s.feature_adoption_score
FROM users u
JOIN customer_stats s ON u.id = s.user_id
WHERE u.email IS NOT NULL
  AND s.updated_at >= NOW() - INTERVAL '1 day'

Map customer_segment to a custom HubSpot contact property (dropdown type), then build HubSpot active lists filtered on that property. Marketing gets segmented audiences without anyone manually tagging contacts — and the segments update every time the sync runs.

This is also how you push segments to ad platforms. Export the same query with an ad_audience column, sync it to Google Ads or Facebook Custom Audiences, and your ad targeting stays current with your actual customer data instead of a CSV someone uploaded three months ago.

Use case 3: Enrich CRM records from your database

Your database knows things your CRM doesn't: product usage metrics, billing status from Stripe, support ticket counts, feature adoption. Reps working deals without this context are flying blind.

SELECT
    c.email,
    p.total_queries_30d,
    p.dashboards_created,
    p.last_dashboard_created_at,
    b.current_plan,
    b.mrr_cents / 100.0 AS mrr,
    b.payment_status,
    t.open_tickets,
    t.avg_resolution_hours,
    CASE
        WHEN p.total_queries_30d > 100 AND b.current_plan = 'free'
            THEN 'power_user_free'
        WHEN b.payment_status = 'past_due'
            THEN 'payment_at_risk'
        ELSE NULL
    END AS rep_alert
FROM crm_contacts c
LEFT JOIN product_usage p ON c.user_id = p.user_id
LEFT JOIN billing b ON c.user_id = b.user_id
LEFT JOIN support_tickets t ON c.user_id = t.user_id
WHERE GREATEST(p.updated_at, b.updated_at, t.updated_at)
      >= NOW() - INTERVAL '1 day'

The rep_alert field is the high-value part. Instead of pushing 15 raw metrics and hoping reps notice patterns, compute the insight in SQL and push a single actionable flag. A rep seeing power_user_free on a contact knows exactly what to do. A rep seeing total_queries_30d: 147 has to do math.

Fastero

Connect your database. Ask questions. Get dashboards.

Postgres, BigQuery, Snowflake, and 10+ sources — live-connected, AI-powered, no dashboard builder learning curve.

Try free →

How this compares to Hightouch and Census

The honest comparison:

Where Hightouch/Census win. If you're running 15+ syncs across Salesforce, HubSpot, Intercom, Braze, Google Ads, and Facebook — with different schedules, field transformations, and audience logic per destination — dedicated reverse ETL tools earn their price. The orchestration layer, sync observability, and per-destination connectors are genuinely hard to replicate. They also support warehouse-native features like dbt model selection that matter if your data team lives in dbt.

Where they're overkill. Three syncs pushing lead scores, segments, and enrichment fields to one or two CRM destinations. This is 80% of what companies under 200 employees actually need from reverse ETL. Paying $10k+/year for a tool that runs three scheduled queries is hard to justify when the same money buys an engineer's time for a month.

Where Fastero fits. You connect your database — not a warehouse, your actual database — write SQL, map fields, and schedule. The sync, the analytics, and the dashboards live in the same tool. No separate vendor for the sync layer. If your reverse ETL needs grow past what a handful of syncs can handle, you can always add a dedicated tool later. But most teams never get there.

Mistakes that seem minor until they aren't

Skipping the dry run. Add LIMIT 10 to your query, point it at a Salesforce sandbox, and verify the field mapping before you touch production. Picklist mismatches, date format issues, and validation rule conflicts all surface here. Five minutes of testing saves a Monday morning fire drill.

No incremental filter. Running a full-table sync daily works at 500 rows. At 50,000 rows it hammers your API limits and slows the sync to a crawl. Add a WHERE updated_at >= NOW() - INTERVAL '1 day' from day one — retrofitting it later means you need to also add change-detection logic you should have built from the start.

Syncing raw data instead of computed insights. Pushing 20 columns of usage metrics to Salesforce creates noise. Reps won't read them. Compute the insight in your SQL — expansion_candidate, at_risk, power_user_free — and push the flag. One actionable field beats twenty raw numbers.

Ignoring per-row failures. A sync job completing doesn't mean every row landed. Bulk API returns per-record results. A validation rule on the Salesforce side can reject half your rows while the job reports success. Check the results, not just the job status.

Not matching sync frequency to source freshness. If your lead scoring model runs once a day, syncing hourly pushes the same data 24 times. Match the schedule to how often the underlying data actually changes.

When you don't need reverse ETL at all

Sometimes the answer is to skip the sync entirely. If the goal is "reps need to see usage data alongside deal info," embedding a live dashboard in HubSpot or linking to a report from the CRM record achieves the same thing without writing data back to the CRM. Less data duplication, no field-mapping maintenance, no API limits to manage.

Reverse ETL earns its place when downstream tools need to act on the data — trigger a workflow, filter an audience, route a lead — not just display it. If you're pushing fields just so someone can eyeball them, a linked dashboard is simpler and always fresh.


Try Fastero free — connect your database and have reverse ETL running in under an hour, no warehouse required. No credit card required.

Ready to try it yourself?

Connect your database, ask questions in plain English, and get live dashboards — in under 2 minutes. No credit card required.