Horse Multi Instance
DevOps & Securityhorse-multi-instanceHorse Multi Instance is an Agent Skill for devops & security published in the HashLoad/horse repository on GitHub: a SKILL.md instruction file an AI agent can load to do this task.
Guidelines for instantiating and configuring independent Horse server instances (THorseInstance) running concurrently on different ports.
How to use this skill
Bring this guide into your coding agent with a prompt tailored to the tool you use.
- Open your project in Codex.
- Copy and paste the prompt below.
- Review files and risks before approving any action.
Inspect the Agent Skill at https://github.com/HashLoad/horse/blob/HEAD/doc/skills/horse-multi-instance/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/horse-multi-instance, but wait for my approval before writing files or running scripts.
Copying this prompt does not install or run the skill. Review third-party files before use.
Horse Multi-Instance
Decoupled Server Contexts
Use THorseInstance when your application needs to expose multiple separate HTTP interfaces (e.g., a public REST API on port 8080 and an admin/telemetry dashboard on port 9090) within the same process.
Each THorseInstance allocates its own isolated:
- Routing tables
- Middleware pipelines
- Active requests telemetry counters
- Lifecycle hooks (
onRequest,preParsing,preValidation,onSend,onResponse)
Declaring and Configuring Instances
Always create and configure THorseInstance explicitly, registering endpoints and middlewares directly on the instance:
var
FPublicApi: THorseInstance;
FAdminPanel: THorseInstance;
begin
// 1. Public API configuration
FPublicApi := THorseInstance.Create;
FPublicApi.Use(Jhonson); // Middleware registered only for FPublicApi
FPublicApi.Get('/api/v1/ping', DoPingHandler);
// 2. Admin Panel configuration
FAdminPanel := THorseInstance.Create;
FAdminPanel.Get('/admin/metrics', DoMetricsHandler);
end;
Starting Listeners Concurrently
Since listeners enter blocking execution loops (depending on the provider and application shape), you must start the physical socket listening in separate threads:
// Start Instance 1 in a background thread
TThread.CreateAnonymousThread(
procedure
begin
FPublicApi.Listen(9001);
end).Start;
// Start Instance 2 in a background thread
TThread.CreateAnonymousThread(
procedure
begin
FAdminPanel.Listen(9002);
end).Start;
Stopping Servers and Freeing Resources
When shutting down, stop listening on each instance before freeing the objects:
FPublicApi.StopListen;
FAdminPanel.StopListen;
FPublicApi.Free;
FAdminPanel.Free;
Design Safeguards & AI Best Practices
- Never write static vars inside local middlewares: Ensure any middleware used inside a
THorseInstancerelies on instance-specific configuration or request-scoped services (Req.Services). - Backward Compatibility: If the project does not require multiple instances, continue using the static
THorsefacade class. It is automatically routed to a default instance under the hood. - FPC/Lazarus Compatibility: When writing samples or libraries for Lazarus, avoid Delphi anonymous procedures inline (
procedure begin end) for route handlers. Use standard global procedures instead.