
PostgreSQL job data feed
Job listings in real tables, queryable with plain SQL.
Any PostgreSQL instance works the same way — managed RDS, Cloud SQL, Neon, or a server you run yourself — because Jobo speaks the standard Postgres wire protocol over TLS. It creates the target table on first sync and upserts on job ID, so a re-push updates rows in place instead of appending duplicates, and the incremental run every 15 minutes only touches jobs that actually changed. The table has a fixed relational shape, which is why transformation pipelines are not offered here: use MongoDB or Elasticsearch if you need arbitrary document structures.
- 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 PostgreSQL instance.
hoststringrequiredDatabase server hostname or IP address.
portnumberrequiredConnection port. Defaults to 5432.
databasestringrequiredTarget database name.
schemastringTarget schema. Defaults to "public".
tablestringTarget table, created automatically. Defaults to "jobs".
usernamestringrequiredDatabase user with write access.
passwordstringrequiredUser password. Encrypted at rest with AES-256.
ssl_modeselectSSL mode: disable, allow, prefer, require, verify-ca, verify-full.
delete_expired_jobsbooleanDelete expired jobs (default). Disable to keep them with an expired_at timestamp.
{
"host": "db.example.com",
"port": 5432,
"database": "jobs_db",
"schema": "public",
"table": "jobs",
"username": "jobo_sync",
"password": "••••••••",
"ssl_mode": "require",
"delete_expired_jobs": true
}How to sync jobs to PostgreSQL
One-time setup. After this, the feed maintains itself.
- 1
Create a least-privilege role for the feed
The feed needs CONNECT on the database plus USAGE and CREATE on one schema — CREATE because it builds the table itself on first sync. It then owns that table, so no further table grants are needed. Do not reuse your application role and never point the feed at a superuser.
sqlCREATE USER jobo_sync WITH PASSWORD 'your_secure_password'; GRANT CONNECT ON DATABASE jobs_db TO jobo_sync; GRANT USAGE, CREATE ON SCHEMA public TO jobo_sync; - 2
Open the network path
Postgres only accepts what you explicitly allow. Confirm listen_addresses covers the interface Jobo reaches, add a pg_hba.conf line for the feed user and Jobo's IP range, reload the configuration, and open the port in your firewall or cloud security group. Contact support for the current egress range.
bash# pg_hba.conf — TLS-only access for the feed role hostssl jobs_db jobo_sync <jobo-ip>/32 scram-sha-256 # apply without a restart sudo -u postgres psql -c 'SELECT pg_reload_conf();' - 3
Point the feed at a dedicated table
Set schema and table to something nothing else writes to, such as public.jobs. The schema must already exist — Jobo creates tables, not schemas. Force resync drops and recreates the configured table, so sharing it with application data will lose that data. Keep ssl_mode at require or higher on anything reachable over the internet.
- 4
Activate and query it
The table and its indexes appear on the first push, and every run after that upserts on job ID. With delete_expired_jobs left on, expired listings are removed outright; turn it off and they stay with an expired_at timestamp you can filter on.
sqlSELECT title, company, locations, apply_url FROM public.jobs WHERE expired_at IS NULL ORDER BY date_posted DESC LIMIT 20;
Common issues
What actually goes wrong when connecting PostgreSQL, and the fix.
The connection test times out or is refused.
Work outwards: firewall or security group first, then listen_addresses, then a matching pg_hba.conf line for the feed user and source IP. A refusal usually means Postgres is not listening on that interface; a timeout usually means the packet never arrived.
The push fails with "permission denied for schema public".
The role can connect but cannot create the table. Grant USAGE and CREATE on the target schema. On PostgreSQL 15 and newer the public schema no longer grants CREATE to everyone, so this bites upgraded clusters in particular.
The push fails because the target schema does not exist.
Automatic creation covers the table only. Run CREATE SCHEMA yourself and grant the feed role USAGE and CREATE on it, or leave the field empty to use public.
Rows the app wrote to the jobs table disappeared.
Force resync drops and recreates the configured table by design. Give the feed a table of its own and have your application read from it rather than write to it.
Best practices
- Give the feed its own table — force resync drops and recreates whatever it points at.
- Grant the role CONNECT plus USAGE and CREATE on one schema, and nothing more.
- Keep ssl_mode at require or higher on any instance reachable over the internet.
- Add your own indexes for the columns you filter and sort on; the feed only creates its own.
- Narrow the feed with location and source filters instead of syncing the whole catalogue.
Other destinations
Start syncing jobs to PostgreSQL
Connect the destination, pick your filters, and let the feed run.