rngo is a dynamic code analyzer that simulates usage, records everything and surfaces patterns
$ rngo eval Simulation time: 2026-10-26 07:38:32 auth-api: 18342 inputs, 18342 outputs auth-postgres: 9120 inputs, 0 outputs inventory-api: 25610 inputs, 25610 outputs inventory-mysql: 14288 inputs, 0 outputs order-api: 12907 inputs, 12907 outputs order-dynamo: 12907 inputs, 0 outputs logs: 0 inputs, 412880 outputs Audit auth-unique-emails: 0 (passed) auth-no-server-errors: 0 (passed) auth-session-expiry-enforced: 0 (passed) inventory-no-negative-stock: 0 (passed) inventory-sku-unique: 0 (passed) inventory-no-server-errors: 0 (passed) order-total-matches-items: 0 (passed) order-no-duplicate-charges: 2 (failed) order-no-server-errors: 0 (passed) order-reserves-inventory: 0 (passed) logs-minimal-errors: 31 (failed) 9 passed, 2 failed
A declarative description of a system's behavior, in terms of a channels, effects and signals. The channels and effects model realistic usage while the signals set expectations for observed behavior.
A channel specifies how to send formatted inputs to and receive outputs from an interface in your system.
Read about channels →channels:
db:
type: stream
command: sqlite3 db.sqlite
format:
type: sql
api:
type: exec
format:
type: template
template: >-
curl -sS -X {{data.method}}
"${API_BASE_URL:-http://localhost:5173}{{{data.path}}}"
{{#if data.body}}
-H 'Content-Type: application/json'
--data '{{json data.body}}'
{{/if}}An effect defines a stream of inputs, which are randomly-generated JSON values with logical (possibly backdated) timestamps.
Read about effects →effects:
users.create:
trigger: hz(100, day)
start: now - years(2)
channel: db
metadata:
table: USERS
generator:
type: object
properties:
id:
type: number
minimum: 1
scale: 0
step: 1
name:
type: string
pattern: .{2,64}
email:
type: function
expression: "'user' + number + '@example.com'"
variables:
number:
type: number
minimum: 10000
maximum: 99999
scale: 0
articles.post:
# …A signal is a SQL query over every channel's inputs and outputs, along with an expected result.
Read about signals →signals:
api-minimum-title-length:
type: sql
query: >
SELECT count(*)
FROM outputs o
JOIN inputs i ON o.input_id = i.id
WHERE i.effect = 'articles.post'
AND length(i.data ->> '$.title') < 10
AND o.data NOT LIKE '%422 Unprocessable Content%';
expect: result == 0
api-no-server-errors:
type: sql
query: >
SELECT count(*) FROM outputs
WHERE channel = 'api' AND data LIKE '%500%';
expect: result == 0
log-minimal-errors:
type: sql
query: >
SELECT count(*) FROM outputs
WHERE channel = 'log' AND data LIKE 'ERROR%';
expect: result < 20