# Connecting clients (primary-following, no proxy)
pg_replica needs no router or VIP in front of it. Every node is an endpoint; the
client is handed all of them and finds the primary itself — exactly like a MongoDB
`mongodb://h1,h2,h3/?replicaSet=...` connection string.
## Why it just works
A `target_session_attrs=read-write` client decides "is this the primary?" by running
`SHOW transaction_read_only` on each host and keeping the one that returns `off`.
pg_replica's fence already sets that for us:
| authorized primary | `off` | connect here |
| standby (in recovery) | `on` | skip |
| fenced ex-primary / lost-quorum minority | `on` | skip |
So the client lands on the current authorized primary, and during a failover or a
loss-of-quorum window it finds **no** read-write host and fails fast — the app retries,
and there is never a write to a fenced node (no split-brain). On failover the only thing
the application does is reconnect.
The connection string (libpq keyword form):
```
host=10.0.0.1,10.0.0.2,10.0.0.3 port=5432 user=app dbname=weido target_session_attrs=read-write connect_timeout=2
```
## Rust — tokio-postgres (verified, see scripts/test-m6-routing.sh)
```rust
use std::str::FromStr;
use tokio_postgres::{Config, NoTls};
let config = Config::from_str(
"host=10.0.0.1,10.0.0.2,10.0.0.3 port=5432 \
user=app dbname=weido target_session_attrs=read-write connect_timeout=2",
)?;
let (client, connection) = config.connect(NoTls).await?; // lands on the primary
```
On a failed query after a failover, drop the client and call `connect` again — it
re-scans and lands on the new primary.
W. connection pool: https://github.com/djc/bb8 / https://github.com/fboulnois/nanopool
## psql / libpq / any libpq-based driver (psycopg, JDBC via pgjdbc, etc.)
```
psql "host=10.0.0.1,10.0.0.2,10.0.0.3 port=5432 user=app dbname=weido target_session_attrs=read-write"
```
## Read scaling (optional)
`target_session_attrs=read-only` (or `prefer-standby` on PG 14+) routes a connection to
a standby instead — useful for read-heavy / ParadeDB search queries that can tolerate
replication lag. Use a separate read-only pool for those.