Horse 3.3: Delphi's Express-style web framework grows a transport buffet
Project brief: Fast, opinionated, minimalist web framework for Delphi. Horse is an Express -inspired web framework for Delphi and Lazarus.
At a glance
- What is it?
- Horse is an Express-inspired web framework for Delphi and Lazarus, and the 3.3 release adds more providers, WebSockets, and lifecycle hooks. The core pitch is minimalism and speed, but the real value now is the choice of transport layers.
- Who is it for?
- Adopt Horse if you are a Delphi or Lazarus developer who wants an Express-like routing API without leaving the Object Pascal world, especially if you need to deploy the same handler code across Indy, http.sys, or async IOCP/epoll providers. Skip it if you need a full-stack framework with built-in ORM and templating, or if you are not prepared to manage middleware and provider dependencies via Boss.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Pascal, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 19, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What Horse actually is
Horse is a web framework for Delphi and Lazarus, modeled on Express.js. The README positions it as fast, opinionated, and minimalist, and the quickstart examples confirm that: you register a route with THorse.Get, pass an anonymous procedure or a named procedure, and call Listen. The API is deliberately small. There is no ORM, no templating engine, no built-in validation. You get routing, request and response objects, middleware, and a set of optional providers that handle the actual HTTP transport. The target user is a Delphi developer who wants to expose a REST API or a small web service without adopting a heavyweight framework like DataSnap or a full MVC stack. Lazarus users are also covered, with an FPC-compatible example that uses {$MODE DELPHI} and a named procedure instead of an anonymous one.
The provider model is the real architecture
The core design decision in Horse is the separation between route handlers and the transport layer. The README explains that a provider owns the socket and hands requests to your handlers, and the same handler code runs under any provider. You select a provider at compile time via a conditional define. The default is Indy on Delphi and fphttpserver on FPC. Optional providers include CrossSocket and mORMot2, which replace the default with async IOCP, epoll, or kqueue I/O. The ICS provider swaps in OverbyteICS with OpenSSL 3.x and 4.x, giving TLS 1.3, SNI, and mTLS. HttpSys is built into Horse and drives the Windows kernel-mode http.sys stack, the same one IIS uses. This means you can write a route handler once and deploy it as a console app, a Windows service, or behind http.sys without changing the handler code. That is a genuine architectural advantage, but it also means you must understand the trade-offs of each provider. Indy is synchronous and blocking, while CrossSocket and epoll are async. The choice affects concurrency behavior and TLS support, not just performance.
Getting it running: Boss and the quickstart
Installation is done with the Boss dependency manager, not with GetIt or manual path configuration. The command is boss install horse. The README also mentions an optional Horse Wizard for IDE integration. The Delphi quickstart is minimal: uses Horse, then THorse.Get('/ping', procedure ... Res.Send('pong')), then THorse.Listen(9000). The Lazarus version requires {$MODE DELPHI}{$H+} and uses a named procedure GetPing. The routing documentation covers route params, groups, and query strings, but the README does not show the exact syntax for those. You have to read doc/routing.md for that. The multi-instance feature lets you run multiple independent HTTP servers in the same process, which is useful for microservices in a single executable. The memory buffer pool is a thread-safe buffer recycling mechanism to eliminate heap allocation, which is the kind of detail that matters for high-throughput servers. The quickstart does not show how to configure the buffer pool, so you would need to check doc/memory-buffer-pool.md for tuning options.
Middleware and lifecycle hooks: where the control lives
Horse supports middleware in the Express tradition. The documentation covers registration order and the Next proc, which is the standard pattern for passing control to the next handler. The lifecycle hooks go further: onRequest, preParsing, preValidation, onSend, and onResponse. These let you intercept the request at different stages, which is useful for logging, authentication, or response modification. The README's middleware catalogue and the writing-middleware doc suggest that the ecosystem is mature, but the README does not list specific middleware names. The AI coding skills section is notable: the project ships pre-packaged instruction files for AI agents like Copilot and Claude, to help them write idiomatic, thread-safe Horse code. That is a practical touch for teams that use AI-assisted development, but it also implies that writing correct Horse middleware requires care, especially around thread safety.
WebSockets and streaming: native but not trivial
The README lists native WebSocket support (RFC 6455) and streaming (Web Streams / SSE) as features. These are not just add-ons; they are part of the core documentation. WebSockets are bidirectional, and streaming covers server-sent events. For a minimalist framework, this is a significant surface. The documentation for WebSockets and streaming is separate, which suggests they have their own configuration and lifecycle. The practical implication is that if you need real-time features, Horse can handle them without pulling in a separate library. But you should verify the provider supports WebSockets; the README does not state that all providers do. The HttpSys provider, for example, might have different WebSocket behavior than Indy. That is a point to check before committing.
The limitations you will hit
Horse is not a full-stack framework. There is no built-in ORM, no view engine, no form validation. You will need to integrate third-party libraries or write your own. The provider model adds complexity: you must choose a provider at compile time, and the default differs between Delphi and Lazarus. That means a codebase that works on Delphi with Indy may not compile on Lazarus without changes, unless you use a provider that supports both. The README warns that ICS is Delphi-only, so cross-platform projects need another option. The multi-instance feature is powerful, but running multiple servers in one process raises questions about port conflicts and resource sharing, which the README does not address. The memory buffer pool is a performance feature, but it also means you need to understand when buffers are released. The documentation for graceful shutdown mentions draining active connections and telemetry, which is good, but it is a feature you must explicitly configure.
The alternative: mORMot or plain Indy
The most direct alternative is mORMot, which is a full-stack framework for Delphi with its own HTTP server, ORM, and JSON serialization. The difference in approach is that mORMot gives you everything out of the box, while Horse makes you assemble the pieces. Horse does offer a mORMot provider, which is telling: you can use Horse's routing on top of mORMot's transport. That is a hybrid approach that some teams take. Another alternative is using Indy directly, but then you lose the Express-style routing and middleware. If you are coming from a JavaScript background, Horse feels familiar, but if you need a batteries-included solution, mORMot is the more integrated path. The choice depends on whether you value minimalism and control or completeness and consistency.
Maintenance and license considerations
Horse is MIT-licensed, which means you can use it in commercial projects without paying licensing fees, and you can modify it. The repository is actively maintained, with recent releases in August 2026, including 3.3.2. The release cadence is frequent, which is good for bug fixes but also means you need to track changes. The documentation is extensive, with a full wiki in doc/, and the AI skills files suggest the project is thinking about modern development workflows. However, the dependency on Boss for installation is a constraint: if your team does not use Boss, you will need to manually manage the source path. The provider ecosystem is partly external, with some providers hosted in separate repositories like horse-provider-crosssocket. That means the core project does not control the quality or maintenance of those providers. You should check each provider's repository for its own license and activity.
Editorial conclusion
Adopt Horse if you are a Delphi or Lazarus developer who wants an Express-like routing API without leaving the Object Pascal world, especially if you need to deploy the same handler code across Indy, http.sys, or async IOCP/epoll providers. Skip it if you need a full-stack framework with built-in ORM and templating, or if you are not prepared to manage middleware and provider dependencies via Boss. Before adopting, verify the compiler support matrix for your exact Delphi or FPC version, confirm the provider you need has the required platform support (ICS is Delphi-only, for example), and test the memory buffer pool behavior under your expected concurrency, since the performance claims hinge on that pool.
Community notes