Build with Zy

HTTP servers and MongoDB

zy serve runs a project containing server.zy and database configuration. Recognized assets in public/ are optional and individually bounded to 1 MiB. It defaults to the current directory. Select another with --project=directory; override the bind address with --host=127.0.0.1 and --port=8000.

fn list_projects(request) {
    return http.json(200, {"data": mongo.list("projects", 20, 0)})
}

http.route("GET", "/api/v1/projects", list_projects)

HTTP exists in serve mode; MongoDB also exists in migrations and workers. All namespaces propagate into imported modules. Regular run remains a local script runner. Top-level code executes at startup and again for every request: use it only for declarations and route registration. Put database writes inside handlers. Each request gets fresh interpreter state; no language globals are shared across requests.

FunctionResult
http.route(method, path, handler[, options])Registers a one-parameter Zy function; optional role restrictions
http.json(status, body)Response value returned by a handler
mongo.list(collection, limit, offset)List of documents, newest first
mongo.get(collection, id)Document or null
mongo.insert(collection, document)Created document
mongo.update(collection, id, fields)Patched document or null
mongo.delete(collection, id)Boolean indicating deletion
mongo.valid_id(id)Boolean ObjectID validation
mongo.find(collection, filter, limit, offset)Bounded filtered documents
mongo.count(collection, filter)Matched document count
mongo.aggregate(collection, stages)Bounded read-only aggregation
mongo.transaction(operations)Atomic batch of 1..25 operations
mongo.create_index(collection, fields, unique)Index name

Methods: GET, POST, PUT, PATCH, DELETE, HEAD. GET automatically supports HEAD. Paths use Go 1.22 ServeMux patterns such as /api/v1/projects/{id}. Duplicate, conflicting, and invalid patterns fail startup. The runtime reserves health and public asset routes. Every path under /api requires bearer authentication.

Handlers receive a map with method, path, params, query, body, and request_id, trace_id, and user. Path/query values are strings; query uses the first value when a key repeats. Empty bodies are null; nonempty bodies must be strict JSON with Content-Type: application/json. Responses are bounded JSON with status 200..599. Use http.json(204, null) for no content. No custom response headers, streaming, WebSockets, or outgoing HTTP client API are included in this version.

MongoDB names contain letters, digits, and underscores and start with a letter. IDs are 24-character hexadecimal strings. Documents expose id instead of _id. Insert adds UTC created_at and updated_at; update preserves creation time. Documents reject _id, dollar-prefixed keys, dotted keys, and null key bytes, including nested objects. MongoDB operations fail with secret-safe Zy I/O errors. Pagination requires limit 1..100 and offset 0..100000. The runtime uses the official MongoDB Go driver.

Environment files load from the project directory. Process environment overrides .env, which overrides atlas-credentials.env. Required settings: MONGODB_URI and an API_KEY of at least 32 characters. Optional: MONGODB_DATABASE (default zy_backend), HOST, PORT, CORS_ORIGINS (explicit origins), and RATE_LIMIT_PER_MINUTE (default 120), AUTH_ENABLED (true), ENABLE_REGISTRATION (false), and MAX_CONCURRENT_REQUESTS (128). Secrets remain outside language globals unless explicitly read with env.get; local file configuration is not installed into the process environment. Optional <username> / <password> placeholders in the URI are escaped using their corresponding configuration values.

Readiness uses a bounded primary ping; unavailable databases cause startup to fail. Ctrl+C or SIGTERM initiates a 15-second HTTP drain and disconnects MongoDB. Request logs contain IDs, method, path, status, and timing, without headers, bodies, or connection strings. Rate limits are in-memory per direct client IP, with a bounded table of 10000 peers; forwarded IP headers are not trusted. Handler execution gets 10 seconds, database calls 5 seconds, and JSON bodies and responses are capped at 1 MiB.

Restart after code changes. Entry and imported sources are prepared once into an immutable snapshot; each request gets fresh state without reparsing files. Serve behind HTTPS and a process supervisor. See backend services for accounts, sessions, roles, query rules, transactions, migrations, jobs, caching, metrics, tracing, and measured performance.

Found something to improve?Edit this page on GitHub ↗
Search guides, language features, and APIs ↵ to open first result