{"id":45311348,"url":"https://github.com/rverton/pgjobs","last_synced_at":"2026-02-21T07:25:25.531Z","repository":{"id":61627334,"uuid":"546501438","full_name":"rverton/pgjobs","owner":"rverton","description":"Go and PostgreSQL job queue blueprint","archived":false,"fork":false,"pushed_at":"2023-01-27T12:57:52.000Z","size":35,"stargazers_count":50,"open_issues_count":1,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-12T09:35:48.120Z","etag":null,"topics":["postgresql","queue"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rverton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-10-06T07:15:10.000Z","updated_at":"2025-04-20T21:38:13.000Z","dependencies_parsed_at":"2023-02-15T09:16:48.061Z","dependency_job_id":null,"html_url":"https://github.com/rverton/pgjobs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rverton/pgjobs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rverton%2Fpgjobs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rverton%2Fpgjobs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rverton%2Fpgjobs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rverton%2Fpgjobs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rverton","download_url":"https://codeload.github.com/rverton/pgjobs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rverton%2Fpgjobs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29676220,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-21T06:23:40.028Z","status":"ssl_error","status_checked_at":"2026-02-21T06:23:39.222Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["postgresql","queue"],"created_at":"2026-02-21T07:25:25.099Z","updated_at":"2026-02-21T07:25:25.524Z","avatar_url":"https://github.com/rverton.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pgjobs, a dead simple postgres job queueing mechanism\n\nThis project aims to be a blueprint for your own job queue solution with Go and\nPostgreSQL. It is recommended to fork this project and adjust the job queue with\nfeatures to your own needs.\n\nBy using Postgres `SKIP LOCKED` feature, this allows to make a performant,\nnon-blocking and independent queue. The technique is described\n[here](https://robinverton.de/blog/queueing-with-postgresql-and-go) and [here](https://www.crunchydata.com/blog/message-queuing-using-native-postgresql).\n\n* Performat: Non-blocking queue mechanism\n* Robust: Jobs will be 'freed' again when a worker crashes\n* Failed jobs will be retried until `MAX_RETRIES`, current attempt is passed as argument\n* Schedule jobs for later execution with `EnqueueAt(ctx, job, \"queuename\", timeAt)`\n* Support for multiple queues\n* Zero dependency\n\n## Example usage\n\nA complete, runnable examples can be found under `./example/`.\n\nFirst define a `pgjobs.Job`, for example in `./jobs/emailUser.go`:\n\n```go\npackage jobs\n\nimport (\n\t\"encoding/json\"\n\t\"log\"\n\n\t\"github.com/rverton/pgjobs\"\n)\n\ntype EmailUser struct {\n\tEmail string\n}\n\nfunc NewEmailUser(email string) *EmailUser {\n\treturn \u0026EmailUser{\n\t\tEmail: email,\n\t}\n}\n\n// the action which should be executed\nfunc (e EmailUser) Perform(attempt int32) error {\n\tlog.Printf(\"emailing %v, attempt=%v\", e.Email, attempt)\n\treturn nil\n}\n\n// this is boilerplate code and does not need to be modified\nfunc (e EmailUser) Load(data string) (pgjobs.Job, error) {\n\tvar n EmailUser\n\terr := json.Unmarshal([]byte(data), \u0026n)\n\treturn n, err\n}\n```\n\nYou can then setup a queue, (optionally) enforce the jobs table schema, and work on queued jobs.\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"example/jobs\"\n\t\"log\"\n\t\"os\"\n\n\t_ \"github.com/jackc/pgx/v5/stdlib\"\n\t\"github.com/rverton/pgjobs\"\n)\n\nfunc main() {\n\tdb, err := sql.Open(\"postgres\", os.Getenv(\"DB_URL\"))\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tctx := context.Background()\n\n\t// initiate queue with postgres connection\n\tqueue := pgjobs.NewQueue(db)\n\tif err := queue.SetupSchema(ctx); err != nil {\n\t\tpanic(err)\n\t}\n\n\tjob := jobs.NewEmailUser(\"foo@example.com\")\n    \n\t// enequeue an example job for immediate execution\n\tif err = queue.Enqueue(context.Background(), job, \"default\"); err != nil {\n\t\tlog.Printf(\"error enqueueing: %v\", err)\n\t}\n    \n\t// enequeue an example job for execution in 10s+\n\tif err = queue.EnqueueAt(context.Background(), job, \"default\", time.Now().Add(10*time.Second)); err != nil {\n\t\tlog.Printf(\"error enqueueing: %v\", err)\n\t}\n\n\t// start worker and pass all processable jobs\n    // note: this worker will only process the passed jobs\n\tqueues := []string{\"default\"}\n\tif err := queue.Worker(ctx, queues, \u0026jobs.EmailUser{}); err != nil {\n\t\tlog.Println(err)\n\t}\n}\n```\n\n## Configuration\n\n* The polling interval for workers can be adjusted via `pgjobs.PollInterval`.\n* For all other configuration, it is currently recommended to create a fork and adjust as needed.\n\n## ToDo\n\n* [X] Make job processing more robust by using a transaction\n* [X] Implement `attempt` handling\n* [X] Add error handling and retries?\n* [X] Add scheduled execution\n* [X] Remove `github.com/lib/pq` dependency\n* [ ] Add more tests (dequeing, reflection)\n* [ ] Add priority queuing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frverton%2Fpgjobs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frverton%2Fpgjobs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frverton%2Fpgjobs/lists"}