{"id":36802574,"url":"https://github.com/pkritiotis/go-outbox","last_synced_at":"2026-01-12T13:35:27.600Z","repository":{"id":39922452,"uuid":"413569416","full_name":"pkritiotis/go-outbox","owner":"pkritiotis","description":"Outbox Pattern implementation in go","archived":false,"fork":false,"pushed_at":"2024-12-30T14:30:24.000Z","size":4723,"stargazers_count":27,"open_issues_count":0,"forks_count":8,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-30T15:29:26.366Z","etag":null,"topics":["example","go","golang","outbox-pattern"],"latest_commit_sha":null,"homepage":"https://pkritiotis.io/outbox-pattern-in-go/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pkritiotis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-04T20:12:31.000Z","updated_at":"2024-12-30T14:30:27.000Z","dependencies_parsed_at":"2024-05-01T10:07:37.025Z","dependency_job_id":"8c31f57f-c526-4f0d-8791-af7e7a2e720f","html_url":"https://github.com/pkritiotis/go-outbox","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/pkritiotis/go-outbox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkritiotis%2Fgo-outbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkritiotis%2Fgo-outbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkritiotis%2Fgo-outbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkritiotis%2Fgo-outbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pkritiotis","download_url":"https://codeload.github.com/pkritiotis/go-outbox/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pkritiotis%2Fgo-outbox/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28339256,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-12T12:22:26.515Z","status":"ssl_error","status_checked_at":"2026-01-12T12:22:10.856Z","response_time":98,"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":["example","go","golang","outbox-pattern"],"created_at":"2026-01-12T13:35:27.431Z","updated_at":"2026-01-12T13:35:27.570Z","avatar_url":"https://github.com/pkritiotis.png","language":"Go","readme":"# Outbox Implementation in Go\n[![Go Build \u0026 Test](https://github.com/pkritiotis/go-outbox/actions/workflows/build-test.yml/badge.svg)](https://github.com/pkritiotis/go-outbox/actions/workflows/build-test.yml)[![golangci-lint](https://github.com/pkritiotis/go-outbox/actions/workflows/lint.yml/badge.svg)](https://github.com/pkritiotis/go-outbox/actions/workflows/lint.yml)\n[![codecov](https://codecov.io/gh/pkritiotis/go-outbox/branch/main/graph/badge.svg?token=KZBBS5MRXP)](https://codecov.io/gh/pkritiotis/go-outbox)\n\nThis project provides a sample implementation of the Transactional Outbox Pattern in Go\n\n# Features\n- Send messages within a `sql.Tx` transaction through the Outbox Pattern\n- Optional Maximum attempts limit for a specific message\n- Outbox row locking so that concurrent outbox workers don't process the same records\n  - Includes a background worker that cleans record locks after a specified time\n- Message Retention. A configurable cleanup worker removes old records after a configurable duration has passed. \n- Extensible message broker interface\n- Extensible data store interface for sql databases\n\n## Currently supported providers\n\n### Message Brokers\n- Kafka\n\n### Database Providers\n- MySQL\n\n# Usage\n\nFor a full example of a mySQL outbox using a Kafka broker check the example [here](./examples/mySQL-Kafka/)\n\n## Create the outbox table\nThe following script creates the outbox table in mySQL\n```mysql\nCREATE TABLE outbox (\n        id varchar(100) NOT NULL,\n        data BLOB NOT NULL,\n        state INT NOT NULL,\n        created_on DATETIME NOT NULL,\n        locked_by varchar(100) NULL,\n        locked_on DATETIME NULL,\n        processed_on DATETIME NULL,\n        number_of_attempts INT NOT NULL,\n        last_attempted_on DATETIME NULL,\n        error varchar(1000) NULL\n)\n```\n## Send a message via the outbox service\n```go\n\ntype SampleMessage struct {\n\tmessage string\n}\n\nfunc main() {\n  \n  //Setup the mysql store\n\tsqlSettings := mysql.Settings{\n\t\tMySQLUsername: \"root\",\n\t\tMySQLPass:     \"a123456\",\n\t\tMySQLHost:     \"localhost\",\n\t\tMySQLDB:       \"outbox\",\n\t\tMySQLPort:     \"3306\",\n\t}\n\tstore, err := mysql.NewStore(sqlSettings)\n\tif err != nil {\n\t\tfmt.Sprintf(\"Could not initialize the store: %v\", err)\n\t\tos.Exit(1)\n\t}\n  \n  // Initialize the outbox\n\trepo := outbox.New(store)\n\n\tdb, _ := sql.Open(\"mysql\",\n\t\tfmt.Sprintf(\"%v:%v@tcp(%v:%v)/%v?parseTime=True\",\n\t\t\tsqlSettings.MySQLUsername, sqlSettings.MySQLPass, sqlSettings.MySQLHost, sqlSettings.MySQLPort, sqlSettings.MySQLDB))\n\n  // Open the transaction\n\ttx, _ := db.BeginTx(context.Background(), nil)\n\n  // Encode the message in a string format\n\tencodedData, _ := json.Marshal(SampleMessage{message: \"ok\"})\n  \n  // Send the message\n\trepo.Add(outbox.Message{\n\t\tKey:   \"sampleKey\",\n\t\tBody:  encodedData,\n\t\tTopic: \"sampleTopic\",\n\t}, tx)\n  \n\ttx.Commit()\n}\n\n```\n## Start the outbox dispatcher\nThe dispatcher can run on the same or different instance of the application that uses the outbox.\nOnce the dispatcher starts, it will periodically check for new outbox messages and push them to the kafka broker\n```go\nfunc main() {\n  \n  //Setup the mysql store\n\tsqlSettings := mysql.Settings{\n\t\tMySQLUsername: \"root\",\n\t\tMySQLPass:     \"a123456\",\n\t\tMySQLHost:     \"localhost\",\n\t\tMySQLDB:       \"outbox\",\n\t\tMySQLPort:     \"3306\",\n\t}\n\tstore, err := mysql.NewStore(sqlSettings)\n\tif err != nil {\n\t\tfmt.Sprintf(\"Could not initialize the store: %v\", err)\n\t\tos.Exit(1)\n\t}\n  \n  //Setup the kafka message broker\n\tc := sarama.NewConfig()\n\tc.Producer.Return.Successes = true\n\tbroker, err := kafka.NewBroker([]string{\"localhost:29092\"}, c)\n\tif err != nil {\n\t\tfmt.Sprintf(\"Could not initialize the message broker: %v\", err)\n\t\tos.Exit(1)\n\t}\n\n  // Initialize the dispatcher\n\t\n\tsettings := outbox.DispatcherSettings{\n      ProcessInterval:           20 * time.Second,\n      LockCheckerInterval:       600 * time.Minute,\n      CleanupWorkerInterval:     60 * time.Second,\n      MaxLockTimeDuration:       5 * time.Minute,\n      MessagesRetentionDuration: 1 * time.Minute,\n\t}\n  \n    d := outbox.NewDispatcher(store, broker, settings, \"1\")\n\n  // Run the dispatcher\n\terrChan := make(chan error)\n\tdoneChan := make(chan struct{})\n\td.Run(errChan, doneChan)\n\tdefer func() { doneChan \u003c- struct{}{} }()\n\terr = \u003c-errChan\n\tfmt.Printf(err.Error())\n}\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkritiotis%2Fgo-outbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpkritiotis%2Fgo-outbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpkritiotis%2Fgo-outbox/lists"}