···11+# Asterism
22+33+Asterism is an [AT Protocol](https://atproto.com) link index that consumes events from across the network. At its core, Asterism is a drop-in replacement for [Constellation](https://constellation.microcosm.blue/), and implements a compatible API. It is intended for app developers that want to own their own stack without rewriting their apps.
44+55+Constellation is vital community infrastructure, and many ATProto apps have been built on its back, including my own, [atbbs.xyz](https://atbbs.xyz/). It can be run on a Raspberry Pi with modest storage requirements, thanks in part to its dependency on Jetstream, which provides a nice, reasonable JSON stream for events.
66+77+Asterism, meanwhile, consumes cryptographically verifiable events directly from the Firehose, and filters them by the collection of your choice. There's no Jetstream in the middle, meaning fewer moving parts. And while Asterism has significant bandwidth requirements, the filtered index is significantly smaller and scales with your application, not with the network.
88+99+> **Early stage.** Functional but *very* incomplete. APIs may change, backfill is rudimentary, and several features are not yet implemented. See [Roadmap](#roadmap).
1010+1111+## What it does
1212+1313+Asterism connects directly to the relay Firehose (`com.atproto.sync.subscribeRepos`), decodes each repo commit's CAR-framed CBOR blocks itself, and recursively walks each record for link references (strong refs, AT-URIs, DIDs, URLs). Links are stored keyed by target, source collection, and field path. On startup it backfills existing repos for your configured collections so the index is useful immediately.
1414+1515+This matters for two reasons:
1616+1717+**Sovereignty** — One fewer dependency and one fewer hop. You're reading straight from the relay, not downstream of someone else's stream processor.
1818+1919+**Verifiability** — Firehose commits carry signed MST proofs; Jetstream strips them and re-serializes as plain JSON. Asterism verifies each record against its repo's signed commit instead of trusting an upstream re-encoding.
2020+2121+```
2222+Relay ──► Jetstream ──► Constellation (preprocessed events)
2323+Relay ──► Asterism (raw commits, filter locally)
2424+```
2525+2626+## Quick start
2727+2828+**Requirements:** Go 1.26+
2929+3030+The typical deployment indexes only the collections your app queries:
3131+3232+```bash
3333+go run ./cmd/asterism/ -collections sh.tangled.graph.follow,sh.tangled.repo.issue,sh.tangled.feed.comment
3434+```
3535+3636+This connects to the relay Firehose, backfills existing repos for those collections in the background, stores links in an sqlite database at `asterism.db`, and serves the query API on `:8081`.
3737+3838+To index all collections (Constellation-equivalent scope, not recommended for sovereign deployments):
3939+4040+```bash
4141+go run ./cmd/asterism/
4242+```
4343+4444+## API
4545+4646+Asterism implements three endpoints from the [microcosm links XRPC namespace](https://constellation.microcosm.blue/):
4747+4848+### `GET /xrpc/blue.microcosm.links.getBacklinksCount`
4949+5050+Count records linking to a subject from a specific collection and field path.
5151+5252+```bash
5353+curl 'http://localhost:8081/xrpc/blue.microcosm.links.getBacklinksCount\
5454+?subject=at%3A%2F%2Fdid%3Aplc%3Aexample%2Fapp.bsky.feed.post%2F3juxgle5hpk2z\
5555+&source=app.bsky.feed.like%3Asubject.uri'
5656+```
5757+5858+Response: `{"total": 42}`
5959+6060+### `GET /xrpc/blue.microcosm.links.getBacklinkDids`
6161+6262+List distinct DIDs that have records linking to a subject. Paginated.
6363+6464+| Parameter | Description |
6565+|---|---|
6666+| `subject` | Target AT-URI, DID, or URL (required) |
6767+| `source` | Collection and field path, e.g. `app.bsky.feed.like:subject.uri` (required) |
6868+| `limit` | Page size, 1–1000 (default 100) |
6969+| `cursor` | Pagination cursor from previous response |
7070+7171+Response: `{"total": 42, "linking_dids": ["did:plc:..."], "cursor": "..."}`
7272+7373+### `GET /xrpc/blue.microcosm.links.getBacklinks`
7474+7575+List source records linking to a subject. Paginated.
7676+7777+| Parameter | Description |
7878+|---|---|
7979+| `subject` | Target AT-URI, DID, or URL (required) |
8080+| `source` | Collection and field path (required) |
8181+| `did` | Filter to specific actor DIDs (repeatable) |
8282+| `limit` | Page size, 1–1000 (default 100) |
8383+| `reverse` | Return links in ascending order (default false) |
8484+| `cursor` | Pagination cursor from previous response |
8585+8686+Response: `{"total": 42, "records": [{"did": "...", "collection": "...", "rkey": "..."}], "cursor": "..."}`
8787+8888+Records identify the linking record by DID, collection, and rkey. Clients must hydrate display data separately (via AppView, PDS, etc.).
8989+9090+## Roadmap
9191+9292+**Near term**
9393+9494+- [ ] `blue.microcosm.links.getManyToMany` endpoint (Constellation parity)
9595+- [ ] Configurable listen address, database path, and relay URL
9696+- [ ] Account deletion and deactivation handling
9797+- [ ] Graceful shutdown and Firehose reconnect
9898+9999+**Medium term**
100100+101101+- [ ] Robust automatic backfill with checkpoint/resume (survive restarts mid-backfill)
102102+- [ ] Backfill progress reporting
103103+- [ ] Metrics and health endpoints
104104+105105+**Longer term**
106106+107107+- [ ] Deployment guides (Docker, single-binary production setup)
108108+- [ ] Pluggable storage backends for larger indexes
109109+- [ ] Horizontal read scaling
110110+111111+## Related projects
112112+113113+- [Constellation](https://constellation.microcosm.blue/) — The reference backlink index from [microcosm.blue](https://www.microcosm.blue/)
114114+- [Spacedust](https://www.microcosm.blue/) — Real-time link stream filtered by target
115115+- [indigo](https://github.com/bluesky-social/indigo) — Go ATProto library used for Firehose, repo, and identity handling
116116+117117+## License
118118+119119+TBD