My understanding, reading between the lines, is that BDR replicates row by row, starting after the COMMIT.
Right - but it replicates transactions with the same transaction boundaries as on the original node. So they only become visible at commit time on the downstream.
e.g.
BEGIN;
INSERT INTO x (a) VALUES (1), (2), (3);
INSERT INTO x (a) VALUES (4);
COMMIT;
BEGIN;
INSERT INTO x (a) VALUES (42);
COMMIT;
replicates as
BEGIN;
INSERT INTO x (a) VALUES (1);
INSERT INTO x (a) VALUES (2);
INSERT INTO x (a) VALUES (3);
INSERT INTO x (a) VALUES (4);
COMMIT;
BEGIN;
INSERT INTO x (a) VALUES (42);
COMMIT;
Note, however, that conflict resolution is row-by-row. So if your downstream already had a row with a = 4, and a was the PRIMARY KEY, that INSERT would get ignored but the rest would proceed normally, and the whole xact would commit as an insert of 1, 2, and 4.
But I need to know the pg_lsn of my last transaction.
Unfortunately, PostgreSQL does not report commit LSNs. I've tried to get optional support for reporting them at commit time, but without success so far. Doing it "right" requires extending the wire protocol, and a few people objected to the backward-compatible way of doing so that I proposed.
The best you can do right now is wait until replay has passed your commit, by doing:
BEGIN;
... do stuff ...;
COMMIT;
SELECT pg_current_xlog_insert_location();
and waiting until replication passes that point. But since this may contain other unimportant work after your commit by the time you call it, and the walsender doesn't rush to replicate unimportant bookkeeping to peers, sometimes it can take a while to pass that LSN. Not usually a problem in production, but can cause stalls in tests and small scale setups.
There's not really an alternative right now though. You can perform a dummy xact after the real one you're interested in to make sure you replicate immediately, at the cost of burning xids, but it must be a real write xact otherwise it'll be silently discarded.