OpenParable
Skip to content
← Back to skills

Horse Multi Instance

DevOps & Security
horse-multi-instance

Horse 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.

View on GitHub ↗
QUICK START

How to use this skill

Bring this guide into your coding agent with a prompt tailored to the tool you use.

  1. Open your project in Codex.
  2. Copy and paste the prompt below.
  3. Review files and risks before approving any action.
Prompt to paste
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

  1. Never write static vars inside local middlewares: Ensure any middleware used inside a THorseInstance relies on instance-specific configuration or request-scoped services (Req.Services).
  2. Backward Compatibility: If the project does not require multiple instances, continue using the static THorse facade class. It is automatically routed to a default instance under the hood.
  3. 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.