{"id":21658394,"url":"https://github.com/zippoxer/bow","last_synced_at":"2026-01-16T04:44:13.353Z","repository":{"id":49102836,"uuid":"131661988","full_name":"zippoxer/bow","owner":"zippoxer","description":"Bow - Minimal embedded database powered by Badger","archived":false,"fork":false,"pushed_at":"2020-11-20T14:18:02.000Z","size":34,"stargazers_count":225,"open_issues_count":4,"forks_count":14,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-07-17T23:16:00.353Z","etag":null,"topics":["badger","database","embedded-database","go","golang"],"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/zippoxer.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}},"created_at":"2018-05-01T00:54:34.000Z","updated_at":"2025-04-08T16:58:19.000Z","dependencies_parsed_at":"2022-09-14T17:22:43.740Z","dependency_job_id":null,"html_url":"https://github.com/zippoxer/bow","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zippoxer/bow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zippoxer%2Fbow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zippoxer%2Fbow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zippoxer%2Fbow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zippoxer%2Fbow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zippoxer","download_url":"https://codeload.github.com/zippoxer/bow/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zippoxer%2Fbow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28477210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T03:13:13.607Z","status":"ssl_error","status_checked_at":"2026-01-16T03:11:47.863Z","response_time":107,"last_error":"SSL_read: 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":["badger","database","embedded-database","go","golang"],"created_at":"2024-11-25T09:29:13.569Z","updated_at":"2026-01-16T04:44:13.338Z","avatar_url":"https://github.com/zippoxer.png","language":"Go","readme":"# Bow [![GoDoc](https://godoc.org/github.com/zippoxer/bow?status.svg)](https://godoc.org/github.com/zippoxer/bow)\n\nBow is a minimal embedded database powered by Badger. \n\nThe mission of Bow is to provide a simple, fast and reliable way to persist structured data for projects that don't need an external database server such as PostgreSQL or MongoDB.\n\nBow is powered by [BadgerDB](https://github.com/dgraph-io/badger), implementing buckets and serialization on top of it.\n\n## Table of Contents\n\n* [Why Badger and not Bolt?](#why-badger-and-not-bolt)\n* [Getting Started](#getting-started)\n  + [Installing](#installing)\n  + [Opening a database](#opening-a-database)\n  + [Defining a structure](#defining-a-structure)\n    - [Randomly generated keys](#randomly-generated-keys)\n  + [Persisting a structure](#persisting-a-structure)\n  + [Retrieving a structure](#retrieving-a-structure)\n  + [Iterating a bucket](#iterating-a-bucket)\n    - [Prefix iteration](#prefix-iteration)\n  + [Serialization](#serialization)\n    - [MessagePack with `tinylib/msgp`](#messagepack-with-tinylibmsgp)\n* [Upcoming](#upcoming)\n  + [Key-only iteration](#key-only-iteration)\n  + [Transactions](#transactions)\n  + [Querying](#querying)\n* [Performance](#performance)\n* [Contributing](#contributing)\n\n## Why Badger and not Bolt?\n[Badger](https://github.com/dgraph-io/badger) is more actively maintained than [bbolt](https://github.com/coreos/bbolt), allows for key-only iteration and has some [very interesting performance characteristics](https://blog.dgraph.io/post/badger/).\n\n## Getting Started\n\n### Installing\n\n```bash\ngo get -u github.com/zippoxer/bow\n```\n\n### Opening a database\n```go\n// Open database under directory \"test\".\ndb, err := bow.Open(\"test\")\nif err != nil {\n    log.Fatal(err)\n}\ndefer db.Close()\n```\n\nWith options:\n\n```go\ndb, err := bow.Open(\"test\",\n    bow.SetCodec(msgp.Codec{}),\n    bow.SetBadgerOptions(badger.DefaultOptions}))\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Defining a structure\n\nEach record in the database has an explicit or implicit unique key.\n\nIf a structure doesn't define a key or has a zero-value key, Bow stores it with a randomly generated key.\n\n```go\ntype Page struct {\n    Body     []byte\n    Tags     []string\n    Created  time.Time\n}\n```\n\nStructures must define a key if they wish to manipulate it.\n\n```go\ntype Page struct {\n    Id      string `bow:\"key\"`\n    Body     []byte\n    Tags     []string\n    Created  time.Time\n}\n```\n\nKeys must be a string, a byte slice, any built-in integer of at least 32 bits (int32, uint32 and above) or a type that implements [`codec.Marshaler`](https://godoc.org/github.com/zippoxer/bow/codec#Marshaler) and [`codec.Unmarshaler`](https://godoc.org/github.com/zippoxer/bow/codec#Unmarshaler).\n\n#### Randomly generated keys\n\n[`Id`](https://godoc.org/github.com/zippoxer/bow#Id) is a convenient placeholder for Bow's randomly generated keys.\n\n```go\ntype Page struct {\n    Id bow.Id // Annotating with `bow:\"key\"` isn't necessary.\n    // ...\n}\n```\n\n`Id.String()` returns a user-friendly representation of `Id`.\n\n`ParseId(string)` parses the user-friendly representation into an `Id`.\n\n`NewId()` generates a random Id. Only necessary when you need to know the inserted Id.\n\n### Persisting a structure\n\n`Put` persists a structure into the bucket. If a record with the same key already exists, then it will be updated.\n\n```go\npage1 := Page{\n    Id:      bow.NewId(),\n    Body:    []byte(\"\u003ch1\u003eExample Domain\u003c/h1\u003e\"),\n    Tags:    []string{\"example\", \"h1\"},\n    Created: time.Now(),\n}\nerr := db.Bucket(\"pages\").Put(page1)\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Retrieving a structure\n\n`Get` retrieves a structure by key from a bucket, returning ErrNotFound if it doesn't exist.\n\n```go\nvar page2 Page\nerr := db.Bucket(\"pages\").Get(page1.Id, \u0026page2)\nif err != nil {\n    log.Fatal(err)\n}\n```\n\n### Iterating a bucket\n\n```go\niter := db.Bucket(\"pages\").Iter()\ndefer iter.Close()\nvar page Page\nfor iter.Next(\u0026page) {\n    log.Println(page.Id.String()) // User-friendly representation of bow.Id.\n}\nif iter.Err() != nil {\n    log.Fatal(err)\n}\n```\n\n#### Prefix iteration\n\nIterate over records whose key starts with a given prefix.\n\nFor example, let's define `Page` with URL as the key:\n\n```go\ntype Page struct {\n    URL  string `bow:\"key\"`\n    Body []byte\n}\n```\n\nFinally, let's iterate over HTTPS pages:\n\n```go\niter := db.Bucket(\"pages\").Prefix(\"https://\")\nvar page Page\nfor iter.Next(\u0026page) {\n    log.Println(page.URL)\n}\n```\n\n### Serialization\n\nBy default, Bow serializes structures with `encoding/json`. You can change that behaviour by passing a type that implements `codec.Codec` via the `bow.SetCodec` option. \n\n#### MessagePack with `tinylib/msgp`\n\nmsgp is a code generation tool and serialization library for [MessagePack](https://msgpack.org/), and it's nearly as fast as [protocol buffers](https://github.com/gogo/protobuf) and about an order of magnitude faster than encoding/json (see [benchmarks](https://github.com/alecthomas/go_serialization_benchmarks)). Bow provides a `codec.Codec` implementation for msgp under the `codec/msgp` package. Here's how to use it:\n\n* Since msgp generates code to serialize structures, you must include the following directive in your Go file:\n\n```go\n//go:generate msgp\n```\n\n* Replace any use of `bow.Id` in your structures with `string`. Since `bow.Id` is a `string`, you can convert between the two without any cost.\n\n* Import `github.com/zippoxer/bow/codec/msgp` and open a database with `msgp.Codec`:\n```go\nbow.Open(\"test\", bow.SetCodec(msgp.Codec{}))\n```\n\nRead more about msgp and it's code generation settings at https://github.com/tinylib/msgp\n\n## Upcoming\n\n### Key-only iteration\n\nSince Badger separates keys from values, key-only iteration should be orders of magnitude faster, at least in some cases, than it's equivalent with Bolt.\n\nBow's key-only iterator is a work in progress.\n\n### Transactions\n\nCross-bucket transactions are a work in progress. See branch [tx](https://github.com/zippoxer/bow/tree/tx).\n\n### Querying\n\nBow doesn't feature a querying mechanism yet. Instead, you must iterate records to query or filter them.\n\nFor example, let's say I want to perform the equivalent of\n\n```SQL\nSELECT * FROM pages WHERE url LIKE '%/home%'\n```\n\nin Bow, I could iterate the pages bucket and filter pages with URLs containing '/home':\n\n```go\nvar matches []Page\niter := db.Bag(\"pages\").Iter()\ndefer iter.Close()\nvar page Page\nfor iter.Next(\u0026page) {\n    if strings.Contains(strings.ToLower(page.URL), \"/home\") {\n        matches = append(matches, page)\n    }\n}\nreturn matches, iter.Err()\n```\n\nMeanwhile, you can try [Storm](https://github.com/asdine/storm) if you want convenient querying.\n\n## Performance\n\nBow is nearly as fast as Badger, and in most cases faster than [Storm](https://github.com/asdine/storm). See [Go Database Benchmarks](https://github.com/zippoxer/go_database_bench).\n\n## Contributing\n\nI welcome any feedback and contribution.\n\nMy priorities right now are tests, documentation and polish.\n\nBow lacks decent tests and documentation for types, functions and methods. Most of Bow's code was written before I had any plan to release it, and I think it needs polish.\n","funding_links":[],"categories":["Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzippoxer%2Fbow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzippoxer%2Fbow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzippoxer%2Fbow/lists"}