Sweet is a high-performance API server framework written in Mojo that targets sub-millisecond latency and 1M+ requests per second throughput. The framework combines AOT compilation, thread-per-core architecture, SIMD acceleration, and Railway Oriented Programming to deliver extreme performance while maintaining type safety and excellent developer ergonomics. This document specifies the functional and non-functional requirements for developers building high-performance APIs with Sweet.
- Sweet: The high-performance API framework being specified
- Handler: A function that processes HTTP requests and returns responses
- Middleware: A component that intercepts and processes requests/responses in the pipeline
- Router: The component that matches incoming request paths to handlers
- Reactor: The async I/O event loop managing network operations
- Parser: The HTTP protocol parser that converts raw bytes to structured requests
- Arena: A memory allocator that provides O(1) bulk deallocation
- ROP: Railway Oriented Programming, an error handling pattern using Result types
- SIMD: Single Instruction Multiple Data, vectorized CPU instructions
- AOT: Ahead-of-Time compilation
- SPSC: Single Producer Single Consumer queue
- DFA: Deterministic Finite Automaton
- StringRef: A zero-copy reference to a string in a buffer
- Plugin: An encapsulated, reusable component that extends framework functionality
- Task_Queue: The background task processing system
- Cron_Scheduler: The time-based job scheduling system
- Validator: A component that checks data against schema constraints
- Serializer: A component that converts data structures to/from JSON
User Story: As an API developer, I want to handle HTTP requests efficiently, so that my API can serve high traffic with low latency.
- WHEN a valid HTTP/1.1 request is received, THE Parser SHALL parse it into an HttpRequest structure
- WHEN parsing HTTP requests, THE Parser SHALL use zero-copy StringRef to avoid allocations
- WHEN parsing HTTP requests, THE Parser SHALL use SIMD instructions for delimiter detection
- WHEN an HTTP request is malformed, THE Parser SHALL return a descriptive ParseError
- THE Parser SHALL support GET, POST, PUT, DELETE, and PATCH methods
- WHEN parsing headers, THE Parser SHALL validate that all header names and values are valid UTF-8
- WHEN parsing is complete, THE Parser SHALL extract query parameters from the path
User Story: As an API developer, I want to define routes with path parameters, so that I can build RESTful APIs with clean URLs.
- WHEN a route is registered, THE Router SHALL compile it into a radix trie at build time
- WHEN an incoming request path matches a registered route, THE Router SHALL return the corresponding handler and extracted parameters
- WHEN a request path does not match any route, THE Router SHALL return a RouteError
- THE Router SHALL support static routes (e.g., /users, /posts)
- THE Router SHALL support parameterized routes (e.g., /users/:id, /posts/:slug)
- THE Router SHALL support wildcard routes (e.g., /static/*)
- WHEN extracting path parameters, THE Router SHALL populate the RouteParams dictionary with parameter names and values
- THE Router SHALL perform route matching in O(path_length) time complexity
User Story: As an API developer, I want to validate request data against schemas, so that invalid data is rejected before reaching my business logic.
- WHEN a validation schema is defined, THE Validator SHALL compile it at build time
- WHEN validating a request, THE Validator SHALL check all fields against their constraints
- WHEN validation fails, THE Validator SHALL return a ValidationError with field-level details
- WHEN validation succeeds, THE Validator SHALL return the validated data structure
- THE Validator SHALL support string constraints (min_length, max_length, pattern)
- THE Validator SHALL support integer constraints (min_value, max_value)
- THE Validator SHALL support nested object validation
- THE Validator SHALL support array validation
- THE Validator SHALL generate validation code at compile time for zero runtime cost
User Story: As an API developer, I want to serialize and deserialize JSON efficiently, so that my API can handle JSON payloads with minimal overhead.
- WHEN serializing a data structure, THE Serializer SHALL produce valid JSON
- WHEN deserializing JSON, THE Serializer SHALL parse it into the target data structure
- WHEN serializing strings, THE Serializer SHALL properly escape special characters
- THE Serializer SHALL use SIMD instructions for delimiter detection during parsing
- THE Serializer SHALL use SIMD instructions for string escaping during serialization
- FOR ALL valid data structures, THE Serializer SHALL satisfy the round-trip property: deserialize(serialize(obj)) equals obj
- WHEN JSON is invalid, THE Serializer SHALL return a descriptive JsonError
User Story: As an API developer, I want to use middleware for cross-cutting concerns, so that I can implement logging, authentication, and CORS without duplicating code.
- WHEN middleware is registered, THE Middleware_Chain SHALL execute it in registration order
- WHEN processing a request, THE Middleware_Chain SHALL invoke on_request hooks before routing
- WHEN processing a request, THE Middleware_Chain SHALL invoke pre_handler hooks before the handler
- WHEN processing a response, THE Middleware_Chain SHALL invoke on_response hooks in reverse order
- WHEN an error occurs, THE Middleware_Chain SHALL invoke on_error hooks to handle the error
- WHEN middleware returns an error, THE Middleware_Chain SHALL short-circuit and skip remaining middleware
- THE Middleware_Chain SHALL allow middleware to transform requests and responses
- THE Middleware_Chain SHALL allow middleware to share state via the request context
User Story: As an API developer, I want explicit error handling with Railway Oriented Programming, so that errors are handled consistently and safely.
- THE Sweet SHALL use Result types for all operations that can fail
- WHEN a Result is Ok, THE Sweet SHALL contain a valid success value
- WHEN a Result is Err, THE Sweet SHALL contain an error with a descriptive message
- THE Result type SHALL support map operations for transforming success values
- THE Result type SHALL support and_then operations for chaining fallible operations
- WHEN an error occurs in a handler, THE Sweet SHALL propagate it through the middleware chain
- WHEN an error reaches the top level, THE Sweet SHALL convert it to an appropriate HTTP error response
- THE Sweet SHALL map ErrorKind.NotFound to HTTP 404
- THE Sweet SHALL map ErrorKind.BadRequest to HTTP 400
- THE Sweet SHALL map ErrorKind.Unauthorized to HTTP 401
- THE Sweet SHALL map ErrorKind.InternalError to HTTP 500
User Story: As an API developer, I want efficient memory management, so that my API doesn't waste resources on allocation overhead.
- WHEN processing a request, THE Arena SHALL allocate memory from a pre-allocated buffer
- WHEN an allocation exceeds arena capacity, THE Arena SHALL return an error
- WHEN request processing completes, THE Arena SHALL reset in O(1) time
- THE Arena SHALL prevent buffer overflows by bounds-checking all allocations
- WHEN the arena is reset, THE Arena SHALL set its offset to zero
- THE Sweet SHALL allocate less than 1KB of memory per typical request
User Story: As an API developer, I want non-blocking I/O, so that my API can handle many concurrent connections efficiently.
- WHERE io_uring is available, THE Reactor SHALL use io_uring for async I/O operations
- WHERE io_uring is not available, THE Reactor SHALL fall back to epoll
- WHEN a socket is ready for reading, THE Reactor SHALL invoke the registered read handler
- WHEN a socket is ready for writing, THE Reactor SHALL invoke the registered write handler
- WHEN a connection is closed, THE Reactor SHALL invoke the close handler and clean up resources
- THE Reactor SHALL submit multiple I/O operations in batches to reduce syscall overhead
- THE Reactor SHALL configure sockets with TCP_NODELAY to minimize latency
- THE Reactor SHALL configure sockets with TCP_QUICKACK to minimize latency
- THE Reactor SHALL use SO_REUSEPORT to distribute connections across worker cores
User Story: As an API developer, I want predictable performance under load, so that my API doesn't suffer from lock contention or cache coherency issues.
- WHEN the server starts, THE Sweet SHALL create one worker thread per configured core
- WHEN a connection arrives, THE Kernel SHALL distribute it to a worker core via SO_REUSEPORT
- WHILE processing a request, THE Worker SHALL use only its own memory and resources
- THE Sweet SHALL ensure no cross-core synchronization is required for request processing
- WHEN multiple cores are active, THE Sweet SHALL scale linearly with core count
- THE Sweet SHALL maintain separate memory arenas per core
- THE Sweet SHALL maintain separate connection pools per core
User Story: As an API developer, I want to offload long-running work to background tasks, so that my API responses remain fast.
- WHEN a task is enqueued, THE Task_Queue SHALL accept it without blocking the request
- WHERE the system has one core, THE Task_Queue SHALL use a local deque for task storage
- WHERE the system has multiple cores, THE Task_Queue SHALL use SPSC buffers with Redis fallback
- WHEN a task is dequeued, THE Task_Executor SHALL invoke the registered handler for that task type
- WHEN a task fails, THE Task_Executor SHALL retry it up to max_retries times
- WHEN a task exceeds max_retries, THE Task_Executor SHALL move it to the dead letter queue
- WHEN retrying a task, THE Task_Executor SHALL apply exponential backoff
- THE Task_Queue SHALL guarantee at-least-once delivery of tasks
User Story: As an API developer, I want to schedule recurring jobs with cron expressions, so that I can automate periodic tasks.
- WHEN a cron job is registered, THE Cron_Scheduler SHALL parse and validate the cron expression
- WHEN a cron job is registered, THE Cron_Scheduler SHALL calculate the next execution time
- WHEN a cron job's execution time arrives, THE Cron_Scheduler SHALL invoke the job handler
- WHEN a cron job completes, THE Cron_Scheduler SHALL calculate the next execution time and reschedule it
- THE Cron_Scheduler SHALL use a min-heap to efficiently determine the next job to execute
- WHEN a cron job fails, THE Cron_Scheduler SHALL log the error and continue with the schedule
- THE Cron_Scheduler SHALL persist job state to the configured job store
- THE Cron_Scheduler SHALL support standard cron expression fields (minute, hour, day, month, weekday)
User Story: As an API developer, I want to make HTTP requests to external services, so that my API can integrate with other systems.
- WHEN making an HTTP request, THE Http_Client SHALL reuse connections from the connection pool
- WHEN no idle connection exists, THE Http_Client SHALL create a new connection
- WHEN a connection is idle beyond the timeout, THE Http_Client SHALL close it
- THE Http_Client SHALL limit connections per host to max_connections_per_host
- THE Http_Client SHALL support GET, POST, PUT, and DELETE methods
- WHEN a request times out, THE Http_Client SHALL return a timeout error
- THE Http_Client SHALL perform DNS resolution asynchronously using a thread pool
- THE Http_Client SHALL cache DNS results to avoid repeated lookups
User Story: As an API developer, I want structured logging with key-value fields, so that I can easily search and analyze logs.
- WHEN logging a message, THE Logger SHALL include a timestamp
- WHEN logging a message, THE Logger SHALL include the log level
- WHEN logging a message, THE Logger SHALL include the source location
- WHEN logging a message, THE Logger SHALL include any provided key-value fields
- THE Logger SHALL support log levels: TRACE, DEBUG, INFO, WARN, ERROR, FATAL
- WHEN the log level is below the configured threshold, THE Logger SHALL skip logging
- THE Logger SHALL use a memory arena for zero-allocation logging
- THE Logger SHALL buffer log writes for performance
- THE Logger SHALL support multiple log sinks (stdout, file, network)
User Story: As an API developer, I want to use plugins for common functionality, so that I don't have to implement features like CORS and authentication from scratch.
- WHEN a plugin is registered, THE Plugin_Registry SHALL invoke its register method
- WHEN the server starts, THE Plugin_Registry SHALL invoke on_startup for all plugins
- WHEN the server stops, THE Plugin_Registry SHALL invoke on_shutdown for all plugins
- THE Plugin SHALL be able to register routes during registration
- THE Plugin SHALL be able to register middleware during registration
- THE Plugin SHALL be able to register lifecycle hooks during registration
- THE Sweet SHALL provide built-in plugins for CORS, JWT authentication, and rate limiting
User Story: As an API developer, I want dependency injection for services, so that my handlers can access databases and caches without manual wiring.
- WHEN a dependency is registered as a singleton, THE DI_Container SHALL create it once and reuse it
- WHEN a dependency is registered as a factory, THE DI_Container SHALL create a new instance on each resolution
- WHEN a handler requests a dependency, THE DI_Container SHALL resolve it at compile time where possible
- THE Sweet SHALL support functional dependency injection via Dependencies parameter
- THE Sweet SHALL support decorator-based dependency injection via @inject annotation
- WHEN a dependency cannot be resolved, THE DI_Container SHALL return a descriptive error
User Story: As an API developer, I want automatic OpenAPI documentation, so that API consumers can understand my endpoints without manual documentation.
- WHEN routes are registered, THE OpenAPI_Generator SHALL extract route metadata
- WHEN generating OpenAPI spec, THE OpenAPI_Generator SHALL include all registered routes
- WHEN generating OpenAPI spec, THE OpenAPI_Generator SHALL include path parameters
- WHEN generating OpenAPI spec, THE OpenAPI_Generator SHALL include request body schemas
- WHEN generating OpenAPI spec, THE OpenAPI_Generator SHALL include response schemas
- THE Sweet SHALL serve the OpenAPI specification at /openapi.json
- THE OpenAPI_Generator SHALL produce valid OpenAPI 3.0 JSON
User Story: As an API developer, I want to configure server settings, so that I can tune performance and behavior for my deployment environment.
- WHEN creating a server configuration, THE Sweet SHALL validate all settings
- IF the port is outside the range 1-65535, THEN THE Sweet SHALL return a validation error
- IF num_workers is less than 1, THEN THE Sweet SHALL return a validation error
- IF TLS is enabled but cert/key paths are missing, THEN THE Sweet SHALL return a validation error
- THE Sweet SHALL support configuration of host, port, and num_workers
- THE Sweet SHALL support configuration of io_uring_entries, tcp_nodelay, tcp_quickack, so_reuseport, and backlog
- THE Sweet SHALL support configuration of TLS certificate and key paths
User Story: As an API developer, I want sub-millisecond latency, so that my API can meet strict SLA requirements.
- THE Sweet SHALL achieve p99 latency under 1 millisecond for simple API operations
- THE Sweet SHALL achieve throughput of 60,000-100,000 requests per second per core
- THE Sweet SHALL scale linearly with core count up to 16+ cores
- THE Sweet SHALL use less than 1KB of memory per typical request
- THE Sweet SHALL parse HTTP requests in 10-20 microseconds using SIMD
- THE Sweet SHALL match routes in 5-10 microseconds using radix trie
- THE Sweet SHALL serialize JSON responses in 20-50 microseconds using SIMD
User Story: As an API developer, I want secure input handling, so that my API is protected against common attacks.
- WHEN validating input, THE Sweet SHALL enforce maximum header size of 8KB
- WHEN validating input, THE Sweet SHALL enforce maximum body size of 10MB (configurable)
- WHEN validating input, THE Sweet SHALL enforce maximum path length of 2KB
- WHEN validating input, THE Sweet SHALL enforce maximum query string length of 4KB
- WHEN validating input, THE Sweet SHALL enforce maximum number of headers of 100
- THE Sweet SHALL validate all string inputs are valid UTF-8
- THE Sweet SHALL bounds-check all buffer accesses to prevent overflows
- WHEN serializing JSON, THE Sweet SHALL escape special characters to prevent injection
- THE Sweet SHALL provide middleware hooks for authentication and authorization
- THE Sweet SHALL support rate limiting via middleware
User Story: As an API developer, I want graceful error handling, so that my API continues serving requests even when errors occur.
- WHEN an HTTP parse error occurs, THE Sweet SHALL return HTTP 400 and continue processing
- WHEN a route is not found, THE Sweet SHALL return HTTP 404 and continue processing
- WHEN validation fails, THE Sweet SHALL return HTTP 422 with field-level errors
- WHEN a handler raises an error, THE Sweet SHALL return HTTP 500 and log the error
- WHEN an I/O error occurs, THE Sweet SHALL close the connection and clean up resources
- WHEN arena exhaustion occurs, THE Sweet SHALL return HTTP 500 and reset the arena
- WHEN a background task fails, THE Sweet SHALL retry it with exponential backoff
- WHEN a cron job fails, THE Sweet SHALL log the error and continue with the schedule
- WHEN any error occurs, THE Sweet SHALL reset the memory arena to prevent leaks
User Story: As an API developer, I want comprehensive testing capabilities, so that I can ensure my API works correctly.
- THE Sweet SHALL provide unit testing support for all components
- THE Sweet SHALL provide property-based testing for parsers, routers, and serializers
- THE Sweet SHALL provide integration testing support for full request-response cycles
- THE Sweet SHALL provide benchmarking tools for performance testing
- THE Sweet SHALL achieve greater than 90% line coverage in tests
- THE Sweet SHALL achieve greater than 85% branch coverage in tests
- THE Sweet SHALL test all error paths and recovery scenarios
User Story: As an API developer, I want intuitive APIs and helpful error messages, so that I can be productive quickly.
- WHEN a route is registered with an invalid pattern, THE Sweet SHALL provide a descriptive compile-time error
- WHEN validation fails, THE Sweet SHALL provide field-level error messages
- WHEN a handler returns an error, THE Sweet SHALL include the error message in logs
- THE Sweet SHALL provide clear examples for common use cases
- THE Sweet SHALL provide comprehensive API documentation
- THE Sweet SHALL use type-safe APIs to prevent runtime errors
- THE Sweet SHALL provide helpful compiler errors for misuse
User Story: As an API developer, I want easy deployment options, so that I can run my API in various environments.
- THE Sweet SHALL compile to a single native binary with no runtime dependencies
- THE Sweet SHALL support running behind a reverse proxy for TLS termination
- THE Sweet SHALL support containerized deployment with Docker
- THE Sweet SHALL support orchestration with Kubernetes
- THE Sweet SHALL provide health check endpoints for load balancers
- THE Sweet SHALL support graceful shutdown to drain in-flight requests
- THE Sweet SHALL support configuration via environment variables
User Story: As an API developer, I want built-in metrics and tracing, so that I can monitor my API's health and performance.
- THE Sweet SHALL expose request latency histograms (p50, p95, p99, p999)
- THE Sweet SHALL expose requests per second metrics per core
- THE Sweet SHALL expose memory arena utilization metrics
- THE Sweet SHALL expose connection pool statistics
- THE Sweet SHALL expose background task queue depth metrics
- THE Sweet SHALL expose error rates by error type
- THE Sweet SHALL support exporting metrics to Prometheus
- THE Sweet SHALL support distributed tracing with trace IDs
User Story: As an API developer, I want to develop on macOS and deploy on Linux, so that I can use my preferred development environment.
- THE Sweet SHALL run on Linux with full feature support
- THE Sweet SHALL run on macOS with epoll fallback for development
- THE Sweet SHALL require x86_64 CPU with AVX2 support for SIMD operations
- THE Sweet SHALL require Linux kernel 5.1+ for io_uring support
- THE Sweet SHALL fall back to epoll on kernels without io_uring
- THE Sweet SHALL require Mojo compiler version 0.26.3 or later