Retrieved article excerpt
Open article Β· Retrieved 2026-09-24T20:37:54.616789+00:00
Backed by Y Combinator
# ClaudeCodexCursorCopilotClaude writes your code.code.code.code.code.Canary tests it.
Canary is the independent tester for code your agents write. It runs your app, tries to break every change, and reports what would have reached production.
Copy the prompt One line for your agent.
Claude Codeβ pocketbaseClaude CodeCodex
Ready for review 1
Database-aware health endpoint
+46 -1 Β· apis/health.go
Database-aware health endpoint
Add a database-aware health endpoint: GET /api/health should ping the data and auxiliary databases and answer 503 when either cannot run SELECT 1.
apis/health.goUpdated
Done. GET /api/health runs SELECT 1 against the data and the auxiliary database before answering. If either probe fails, the endpoint logs the error and returns HTTP 503 with code 503 and message "API is unhealthy." Each probe is bounded by a 3 second timeout derived from the request context. The successful response, including the superuser-only fields, is unchanged.
β Agent Claude Code
apis/health.go
@@ -1,9 +1,12 @@
package apis
import (
+ "context"
"net/http"
"slices"
+ "time"
+ "github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/tools/router"
)
@@ -14,7 +17,12 @@ func bindHealthApi(app core.App, rg \*router.RouterGroup[\*core.RequestEvent]) {
subGroup.GET("", healthCheck)
}
-// healthCheck returns a 200 OK response if the server is healthy.
+// healthCheckDBTimeout is the max time the health check waits for each database ping.
+const healthCheckDBTimeout = 3 \* time.Second
+
+// healthCheck returns a 200 OK response if the server is healthy
+// (aka. the HTTP server is up and the data and aux databases answer a trivial query),
+// otherwise a 503 Service Unavailable response.
func healthCheck(e \*core.RequestEvent) error {
resp := struct {
Message string `json:"message"`
@@ -25,6 +33,16 @@ func healthCheck(e \*core.RequestEvent) error {
Message: "API is healthy.",
}
+ if err := pingHealthDBs(e); err != nil {
+ e.App.Logger().Error("Health check database ping failed", "error", err)
+
+ resp.Code = http.StatusServiceUnavailable
+ resp.Message = "API is unhealthy."
+ resp.Data = map[string]any{}
+
+ return e.JSON(http.StatusServiceUnavailable, resp)
+ }
+
// @todo evaluate whether it is worth removing the extra info from the health endpoint
if e.HasSuperuserAuth() {
resp.Data = make(map[string]any, 3)
@@ -52,3 +70,30 @@ func healthCheck(e \*core.RequestEvent) error {
return e.JSON(http.StatusOK, resp)
}
+
+// pingHealthDBs runs a trivial query against the data and aux databases
+// and returns the first error it encounters.
+//
+// Each database gets its own healthCheckDBTimeout budget (derived from
+// the request context so that a client cancellation still stops the probe).
+func pingHealthDBs(e \*core.RequestEvent) error {
+ if err := pingHealthDB(e.Request.Context(), e.App.DB()); err != nil {
+ return err
+ }
+
+ if err := pingHealthDB(e.Request.Context(), e.App.AuxDB()); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// pingHealthDB runs SELECT 1 against the provided db within healthCheckDBTimeout.
+func pingHealthDB(parent context.Context, db dbx.Builder) error {
+ ctx, cancel := context.WithTimeout(parent, healthCheckDBTimeout)
+ defer cancel()
+
+ var result int
+
+ return db.NewQuery("SELECT 1").WithContext(ctx).Row(&result)
+}
0K+
bugs found before merge
0K+
engineer hours saved
0%+
fix rate
0%
rated P0 / P1
01 / Install
Get started in under 2 minutes.
Works with Claude Code, Cursor, Codex and any of your agents
01
Paste the prompt
02
Connect your stack
03
Catch failures
Paste this into your coding agent
`` Install the Canary CLI with `npm i -g @runcanary/cli`, then run `canary skills` and follow its instructions to onboard this repository. ``
Copy
02 / The problem
## The blast radius is the unknown unknown.The blast radius is the unknown unknown.
1. 01
Your agents raise more PRs than your team can review. Review turned into a skim.
2. 02
The tests pass. The same agent wrote them, and nobody on your team reads them. Nor should they.
3. 03
The bug shows up as a Slack message from a customer, or a page that wakes your on-call at 2am.
4. Teams on Canary have seen bug reports on new code go down, and on-call pages with them.
03 / How it works
## Release the flock.Release the flock.
One loop. From your coding agent, and on every pull request.
Reviewers read the diff. Canary runs the app, tries to break the diff, and reports the blind spots you missed.
01Read
02Run
03Break
04Verify
01
Canary reads the diff and your codebase and maps every flow the change can reach.
βΈ diff: apis/health.go Β· +46 β1
βΈ reach: GET /api/health Β· backups page Β· superuser page Β· proxy header
βΈ 5 tests queued
$
04 / Where it runs
## Runs where you write code.Runs where you write code.
Two triggers. One loop. Every run ends in a report.
01In your agent
02On every PR
03Fix loop
04Report
01
Before your agent calls a task done. Canary snapshots the uncommitted tree, boots it in a clean sandbox and tests it. No commit, no PR.
$ canary verify
βΈ snapshot: working tree Β· 4 files Β· nothing committed
βΈ sandbox: clean boot Β· pocketbase
βΈ 5 tests queued β¦ running
$
05 / Integrations
## Works where you work.Works where you work.
Canary reads the context you already have, and files every break back to your coding agent.
GitHub
Linear
Sentry
Datadog
Notion
Slack
CANARYtests
Claude Code
PR Β· CLI Β· MCP
06 / Examples
## Every failure arrives with proof.Every failure arrives with proof.
Four failures Canary caught on real customer pull requests.
01Wrong org's file02One click, two records03Fetches any URL04Delete wipes all
test replay Β· api/documentsREPLAY
test Β· api/documents
βΈ auth as Org A Β· request a review image by storageId
βΈ swap storageId β a document owned by Org B
β server resolves it Β· Org B's private file returned to Org A
Β· one customer can open another customer's file
$
Case file Β· api/documentsP0
staging Β· found autonomously in 6m 09s
βΈ
Test
swap storageId to another org's document
β
Break
another org's private file opens for the caller
β
Root cause
image-URL resolver looks up by storageId with no org-ownership check
+
Suggested fix
β resolveImage(storageId)
+ resolveImage(storageId, { orgId: caller.orgId })
β
Regression armed
cross-org.storageId reruns on every PR
07 / Research
## Field notes from the frontier.Field notes from the frontier.
We publish what we learn measuring AI against real, messy codebases.
[Benchmark15 min read Β· March 2026
### QA-Bench v0: measuring how AI models handle code verification
Given a real pull request on a production codebase, can a model find every affected user flow and catch what breaks? We put a purpose-built agent against the frontier models across 35 PRs on four production-scale repos.
Read the benchmark β
Overall accuracy Β· QA-Bench v0
Canary83.1
GPT-5.480.2
Claude Code78
Sonnet 4.673.2](https://www.runcanary.ai/blog/qa-bench-v0)
08 / Your move
## Find it before your users do.Find it before your users do.
Put the flock on your next pull request. It runs on every one after.
Copy the prompt One line for your agent.