Database

Supabase job data feed

A live jobs table in your Supabase project, no scraper required.

A Supabase project is ordinary PostgreSQL underneath, so Jobo connects through the session pooler over the Postgres wire protocol rather than the REST API. The table is created automatically on the first sync and every push upserts on job ID, so rows update in place and the 15-minute incremental run only touches jobs that changed. From then on it behaves like any other table in your project — visible in the Table Editor, queryable from the Supabase client, and served by PostgREST once you have put a policy on it.

Sync
Incremental, every 15 min
Deduplication
Upsert on job ID
Pipelines
Not supported
Credentials
AES-256 at rest

Connection configuration

The fields Jobo collects to reach your Supabase instance.

hoststringrequired

Pooler host from your Supabase dashboard (Connect → Session pooler).

portnumberrequired

5432 for the session pooler (recommended), 6543 for the transaction pooler.

databasestringrequired

Target database name. Defaults to "postgres".

schemastring

Target schema. Defaults to "public".

tablestring

Target table, created automatically. Defaults to "jobs".

usernamestringrequired

postgres.<project-ref> when connecting through the pooler.

passwordstringrequired

Database password from Project Settings → Database. Encrypted at rest with AES-256.

ssl_modeselect

SSL mode: require (default), verify-ca, verify-full.

delete_expired_jobsboolean

Delete expired jobs (default). Disable to keep them with an expired_at timestamp.

Supabase config
{
  "host": "aws-0-eu-central-1.pooler.supabase.com",
  "port": 5432,
  "database": "postgres",
  "schema": "public",
  "table": "jobs",
  "username": "postgres.your-project-ref",
  "password": "••••••••",
  "ssl_mode": "require",
  "delete_expired_jobs": true
}

How to sync jobs to Supabase

One-time setup. After this, the feed maintains itself.

  1. 1

    Copy the session pooler details

    In the Supabase dashboard open Connect → Session pooler and copy the host, port, database, and username. Use the pooler rather than the direct db.<ref>.supabase.co host, which resolves to IPv6 only. Port 5432 is the session pooler; 6543 is the transaction pooler and is not a drop-in substitute.

    json
    {
      "host": "aws-0-eu-central-1.pooler.supabase.com",
      "port": 5432,
      "database": "postgres",
      "username": "postgres.your-project-ref"
    }
  2. 2

    Fetch the database password

    The password sits under Project Settings → Database, separate from the connection panel. It is the database password, not your anon or service-role API key — those are for PostgREST and will not authenticate a Postgres connection. Reset it there if you never recorded it; Jobo stores whatever you paste encrypted at rest with AES-256.

  3. 3

    Point the feed at a dedicated table

    Use a table nothing else in your project writes to, such as public.jobs. Jobo creates it on first sync and upserts on job ID. A table created this way has Row Level Security off, which on the public schema means the anon key can read it — enable RLS and add an explicit read policy before you ship. Force resync drops and recreates the table, taking any policies and custom indexes with it, so keep the statements handy.

    sql
    ALTER TABLE public.jobs ENABLE ROW LEVEL SECURITY;
    
    CREATE POLICY "jobs are publicly readable"
      ON public.jobs FOR SELECT TO anon USING (true);
  4. 4

    Read it from your app

    Once the first push finishes the table is served like any other, so the Supabase client you already use can query it directly. Fresh rows arrive every 15 minutes without any further action.

    javascript
    const { data } = await supabase
      .from('jobs')
      .select('title, company, locations, apply_url')
      .order('date_posted', { ascending: false })
      .limit(20)

Common issues

What actually goes wrong when connecting Supabase, and the fix.

high

Connection times out or the host fails to resolve.

You are almost certainly on the direct db.<ref>.supabase.co host, which is IPv6-only. Switch to the session pooler host on port 5432 from Connect → Session pooler.

high

Authentication fails with an otherwise correct password.

Through the pooler the username is postgres.<project-ref>, not plain postgres. Copy it verbatim from the connect panel. If it still fails, check you used the database password rather than an API key.

medium

Pushes fail with a prepared statement error on port 6543.

That is the transaction pooler, which multiplexes connections and does not keep session state. Use port 5432, the session pooler, for this destination.

medium

Row Level Security policies vanished after a force resync.

Force resync drops and recreates the table, and dropping a table drops its policies, grants, and indexes. Keep those statements in a migration you can re-run, and never point the feed at a table your app writes to.

Best practices

  • Use the session pooler on port 5432, never the IPv6-only direct host.
  • Give the feed its own table and let the rest of the project read from it.
  • Enable RLS with an explicit read policy — an auto-created public table is otherwise exposed.
  • Re-apply policies and indexes after a force resync; dropping the table drops them too.
  • Keep ssl_mode at require or higher; the pooler terminates TLS so it costs nothing.

Start syncing jobs to Supabase

Connect the destination, pick your filters, and let the feed run.