Postgres deadlocks on concurrent upserts
I can think of three solutions:
You insert only one row per statement, but that's inefficient.
You sort the rows before inserting them.
You retry a transaction if it gets a deadlock or serialization error.
I'd prefer the third solution unless the errors happen very often.
Your query's syntax allows ordering the values easily:
INSERT INTO documents (version, source, source_id, ingestion_date) SELECT * FROM ( VALUES (0, 'googledrive', 'alpha', '2017-09-21T07:03:51.074Z'), (0, 'googledrive', 'beta', '2017-09-21T07:03:51.074Z') (0, 'googledrive', 'gamma', '2017-09-21T07:03:51.074Z'), (0, 'googledrive', 'delta', '2017-09-21T07:03:51.074Z'), (0, 'googledrive', 'epsilon', '2017-09-21T07:03:51.074Z'), (0, 'googledrive', 'zeta', '2017-09-21T07:03:51.074Z') ) AS v ORDER BY source, source_id ON CONFLICT (source, source_id)
This should solve your problem. Performance should be nice, as the sort will be tiny.