kinetis / framework
The Runtime-Aware PHP Framework
Requires
- php: ^8.4
- ext-fileinfo: *
- nyholm/psr7: ^1.8
- nyholm/psr7-server: ^1.1
- psr/container: ^2.0
- psr/event-dispatcher: ^1.0
- psr/http-message: ^2.0
- psr/http-server-middleware: ^1.0
- psr/log: ^3.0
- psr/simple-cache: ^3.0
- revolt/event-loop: ^1.0
- vlucas/phpdotenv: ^5.6
Requires (Dev)
- infection/infection: ^0.34.2
- nikic/php-parser: ^5.0
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.0
- vimeo/psalm: ^6.16
Suggests
- ext-event: An OS-native Revolt event-loop backend (epoll), removing select()'s 1024 fd-number ceiling. Needed when the loop watches real sockets (native Postgres driver, Redis, HTTP client) in a FrankenPHP worker process; a MySQL-only deployment does not need it. ext-uv/ext-ev work equally.
README
The non-blocking PHP framework for API-first applications
Runs on persistent-worker runtimes, with AI agents as first-class API clients
Kinetis targets the same class of application a modern API is expected to be: typed request and response contracts, OpenAPI described automatically rather than hand-maintained, genuinely non-blocking under real concurrent load, and native support for AI agents as first-class API clients, not an afterthought bolted on later.
Attribute-driven routing and validation replace config files to keep in sync with the code:
use Kinetis\Http\Attributes\Body; use Kinetis\Http\Attributes\Post; final readonly class UserController { #[Post('/users', status: 201)] public function store(#[Body] CreateUserRequest $data): UserResponse { return new UserResponse(name: $data->name, email: $data->email); } }
Request-scope isolation is a hard, enforced guarantee instead of a
convention. And speed comes from two different places, not one: real
Fiber-based concurrency over a Revolt event loop instead of blocking calls
wrapped in the appearance of async, and ahead-of-time compilation
(kinetis build) so a request in production pays reflection's cost once,
not on every single one it serves.
Kinetis is designed around FrankenPHP's worker mode — a PHP process that boots once and serves thousands of requests — as its primary target, though the same application code also runs correctly under classic PHP-FPM and AWS Lambda (via Bref): the runtime is an adapter Kinetis talks to, not an assumption baked into the framework itself.
Highlights
- Runtime-adapter architecture — the same
public/index.phpruns unmodified under FrankenPHP, PHP-FPM, or AWS Lambda;RuntimeDetectorpicks the right adapter with zero configuration. - A two-tier container (
AppScope+RequestScope) that makes request-scope isolation an enforced guarantee, not a convention — backed by a PHPStan rule that bans straystaticstate. - Attribute-based routing, validation, and OpenAPI — typed DTOs
validated before your controller ever runs, with a zero-config Swagger
UI at
/docs. - Fiber-based concurrency (
Kinetis\Async\concurrently()) over Revolt, plus Revolt-native MySQL, Postgres, and Redis clients — no blocking drivers, no hand-rolled wire protocols. - A native MCP server — stdio and Streamable HTTP transports, so an AI agent can call your application's own tools and resources the same way it calls anything else.
- A PSR-14 event dispatcher — attribute-driven listener registration,
with
ShouldQueuefor deferring a listener onto a queue instead of running it inline. - Production AOT caching — routes, validation plans, and MCP
registrations compiled once (
bin/kinetis build). A boot-and-die runtime skips re-registering everything from scratch on every request; even a persistent worker skips the per-dispatch reflection cost that otherwise recurs on every single request regardless.
Installation
composer require kinetis/framework
Requires PHP 8.4 or later. See Getting Started for a complete walkthrough, including running under FrankenPHP.
Configuration
Core reads from the environment (or a .env file at the project root)
via Kinetis\Config:
| Key | Default | Purpose |
|---|---|---|
APP_ENV |
production |
development or production — selects live discovery vs. the AOT cache. Anything unrecognized means production. |
MAX_BODY_SIZE |
2097152 |
Request-body cap in bytes, enforced against declared Content-Length and actual bytes read. |
ROUTE_DISCOVERY_PATHS |
— | Restricts the HTTP-controller scan to comma-separated sub-paths, relative to each PSR-4 base directory. |
COMMAND_DISCOVERY_PATHS |
— | The same, for CLI commands. |
MCP_DISCOVERY_PATHS |
— | The same, for MCP tools and resources. |
MIDDLEWARE_DISCOVERY_PATHS |
— | The same, for global middleware and middleware groups. |
LISTENER_DISCOVERY_PATHS |
— | The same, for event listeners. |
Each package documents its own keys (DB_*, REDIS_*, QUEUE_*, ...)
in its own README; the full reference across every package is at
docs.kinetis.dev/config.html.
Packages
Kinetis core (kinetis/framework) ships as a single package. A few optional pieces live as separate packages, each with its own
dependencies:
| Package | What it adds |
|---|---|
kinetis/persistence |
Request-scoped SQL transaction safety net (TransactionGuard) and connection-pool factory for MySQL/Postgres |
kinetis/cache-redis |
Redis-backed PSR-16 CacheInterface — single-node, Cluster, and TLS |
kinetis/auth |
Opaque Bearer-token authentication middleware |
kinetis/auth-jwt |
Stateless JWT authentication (HS256/RS256), with optional per-token revocation |
kinetis/migrations |
A thin database migration runner — raw SQL up()/down(), no schema-diffing |
kinetis/query-builder |
A thin, parameterized SQL query builder for MySQL/Postgres — not an ORM |
kinetis/queue |
A backend-agnostic background job queue — Redis and SQL backends included |
kinetis/queue-sqs |
An Amazon SQS backend for kinetis/queue — non-blocking via kinetis/revolt-http-client |
kinetis/storage |
File storage on League\Flysystem — a genuinely non-blocking, Amp\File-backed local adapter |
kinetis/storage-s3 |
S3 (and S3-compatible) storage for kinetis/storage's FILESYSTEM_DRIVER=s3 — non-blocking via kinetis/revolt-http-client |
kinetis/mailer |
Mail sending via Symfony\Component\Mailer — API-based transports non-blocking via kinetis/revolt-http-client |
kinetis/revolt-http-client |
A Revolt-native Symfony HttpClientInterface — usable standalone, no Kinetis required |
kinetis/bref-adapter |
AWS Lambda (Bref) runtime adapter, for multipart/form-data support Lambda specifically needs |
Documentation
The full documentation is hosted at docs.kinetis.dev — start with Getting Started or Core Concepts.
Development
Kinetis is built and tested exclusively through Docker — running
php/composer directly on the host is deliberately avoided throughout
this codebase's own development:
# tests docker run --rm -v "$PWD":/app -w /app php:8.4-cli-alpine php vendor/bin/phpunit # static analysis (PHPStan level 8) docker run --rm -v "$PWD":/app -w /app php:8.4-cli-alpine php vendor/bin/phpstan analyse --no-progress
License
Kinetis is open-sourced under the MIT license.