ALTER TABLE documents ADD COLUMN version BIGINT NOT NULL DEFAULT 0;
package store
import (
"context"
"errors"
"github.com/jackc/pgx/v5/pgxpool"
)
var ErrConflict = errors.New("conflict")
func UpdateDoc(ctx context.Context, db *pgxpool.Pool, id string, version int64, body string) error {
ct, err := db.Exec(ctx,
`UPDATE documents SET body=$3, version=version+1 WHERE id=$1 AND version=$2`,
id, version, body,
)
if err != nil {
return err
}
if ct.RowsAffected() == 0 {
return ErrConflict
}
return nil
}
When multiple clients can update the same record, I prefer optimistic locking over heavy row locks. The idea is simple: every row has a version that increments on each update. The update statement includes WHERE id=$1 AND version=$2, so if someone else updated the row first, your update affects zero rows and you return a 409 Conflict. This is a clean, DB-native way to detect lost updates without forcing a transaction to hold locks while the client thinks. The operational benefit is better concurrency under load, especially for “edit settings” style endpoints. In practice, the API returns the latest record so the client can re-apply changes or show a merge UI. It’s a small schema change with a big correctness payoff.
Related snips
package api
import (
"net/http"
"runtime/debug"
)
Expose build metadata for debugging deploys
package dbutil
import (
"context"
"github.com/jackc/pgconn"
Retry Postgres serialization failures with bounded attempts
require "csv"
class PeopleCsvStream
include Enumerable
HEADERS = %w[id full_name email signed_up_at plan].freeze
Resilient CSV Export as a Streamed Response
use crossbeam::channel::unbounded;
use std::thread;
fn main() {
let (tx, rx) = unbounded();
Crossbeam for advanced concurrent data structures
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
if (success) {
Promises and async/await patterns for asynchronous JavaScript
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
Channels (mpsc) for message passing between threads
Share this code
Here's the card — post it anywhere.