WH

whmcs-spot-instances

Manages bidding and reliability for spot instances in cloud hosting.

Install

mkdir -p .claude/skills/whmcs-spot-instances && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/11136" && unzip -o skill.zip -d .claude/skills/whmcs-spot-instances && rm skill.zip

Installs to .claude/skills/whmcs-spot-instances

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Spot instance handling for WHMCS cloud services
47 charsno explicit “when” trigger
Advanced

Key capabilities

  • Launch spot instances
  • Calculate optimal bid prices
  • Handle instance interruptions
  • Monitor interruption status
  • Fallback to on-demand instances

How it works

It manages the lifecycle of spot instances by integrating bidding engines and interruption handlers within the WHMCS framework.

Inputs & outputs

You give it
Instance configuration parameters
You get back
Spot instance status

When to use whmcs-spot-instances

  • Cloud resource optimization
  • Setting up spot instance bidding
  • Handling instance interruptions

About this skill

WHMCS Spot Instance Handling Skill

Overview

This skill provides patterns and implementations for managing spot instances in WHMCS, including bidding strategies, interruption handling, fallback mechanisms, and cost optimization.

Implementation Patterns

Spot Instance Manager

<?php
/**
 * WHMCS Spot Instance Management
 * Handles spot/preemptible instance lifecycle
 */

namespace WHMCS\Module\Server\Spot;

class SpotInstanceManager {
    private $db;
    private $biddingEngine;
    private $interruptionHandler;

    public function __construct() {
        $this->db = \WHMCS\Database\Capsule::connection();
        $this->biddingEngine = new BiddingEngine();
        $this->interruptionHandler = new InterruptionHandler();
    }

    /**
     * Launch spot instance
     */
    public function launchSpot(array $params): array {
        $spotId = 'spot_' . bin2hex(random_bytes(12));

        $spotInstance = [
            'id' => $spotId,
            'service_id' => $params['service_id'] ?? null,
            'customer_id' => $params['customer_id'],
            'instance_type' => $params['instance_type'],
            'quantity' => $params['quantity'] ?? 1,
            'region' => $params['region'] ?? 'default',
            'max_bid_price' => $params['max_bid_price'],
            'bidding_strategy' => $params['strategy'] ?? 'optimal',
            'fallback_to_ondemand' => $params['fallback'] ?? true,
            'interrupt_grace_period' => $params['grace_period'] ?? 120,
            'status' => 'requesting',
            'created_at' => date('Y-m-d H:i:s')
        ];

        $this->db->insert('mod_spot_instances', $spotInstance);

        // Submit spot request to cloud provider
        $requestResult = $this->submitSpotRequest($spotInstance);

        if ($requestResult['success']) {
            $this->db->update('mod_spot_instances', [
                'request_id' => $requestResult['request_id'],
                'status' => 'open'
            ], ['id' => $spotId]);
        }

        return [
            'success' => true,
            'spot_id' => $spotId,
            'request_id' => $requestResult['request_id'] ?? null
        ];
    }

    /**
     * Get spot request status
     */
    public function getRequestStatus(string $spotId): array {
        $spot = $this->getSpotInstance($spotId);

        if (!$spot) {
            throw new \Exception("Spot instance not found: {$spotId}");
        }

        // Check with cloud provider
        $cloudStatus = $this->checkCloudRequestStatus($spot['request_id']);

        return [
            'spot_id' => $spotId,
            'request_id' => $spot['request_id'],
            'status' => $cloudStatus['status'],
            'current_price' => $cloudStatus['current_price'],
            'fulfilled_instances' => $cloudStatus['fulfilled'],
            'interruption_count' => $spot['interruption_count']
        ];
    }

    /**
     * Handle spot interruption
     */
    public function handleInterruption(array $interruptionData): array {
        $spotId = $interruptionData['spot_id'];
        $spot = $this->getSpotInstance($spotId);

        if (!$spot) {
            throw new \Exception("Spot instance not found: {$spotId}");
        }

        // Record interruption
        $this->db->insert('mod_spot_interruptions', [
            'spot_id' => $spotId,
            'instance_id' => $interruptionData['instance_id'],
            'interruption_time' => date('Y-m-d H:i:s'),
            'reason' => $interruptionData['reason'] ?? 'price_exceeded',
            'notice_received_at' => $interruptionData['notice_time'] ?? date('Y-m-d H:i:s')
        ]);

        // Update interruption count
        $this->db->update('mod_spot_instances', [
            'interruption_count' => $spot['interruption_count'] + 1
        ], ['id' => $spotId]);

        // Execute graceful shutdown
        $this->interruptionHandler->executeGracefulShutdown($spotId);

        // Check for fallback
        if ($spot['fallback_to_ondemand']) {
            $this->launchFallbackInstance($spotId);
        }

        return [
            'success' => true,
            'spot_id' => $spotId,
            'handled' => true,
            'fallback_launched' => $spot['fallback_to_ondemand']
        ];
    }

    /**
     * Calculate optimal bid price
     */
    public function calculateOptimalBid(string $instanceType, string $region): array {
        return $this->biddingEngine->calculateOptimalBid($instanceType, $region);
    }

    /**
     * Set up interruption monitoring
     */
    public function setupInterruptionMonitoring(string $spotId): array {
        $spot = $this->getSpotInstance($spotId);

        if (!$spot) {
            throw new \Exception("Spot instance not found: {$spotId}");
        }

        // Create scheduled task to check for interruptions
        $monitorConfig = [
            'spot_id' => $spotId,
            'check_interval' => 60,
            'grace_period' => $spot['interrupt_grace_period'],
            'notification_enabled' => true
        ];

        $this->db->update('mod_spot_instances', [
            'monitoring_config' => json_encode($monitorConfig)
        ], ['id' => $spotId]);

        return [
            'success' => true,
            'spot_id' => $spotId,
            'monitoring_enabled' => true
        ];
    }

    /**
     * List spot instances
     */
    public function listSpotInstances(array $filters = []): array {
        $query = "SELECT s.*, c.companyname as customer_name
                  FROM mod_spot_instances s
                  LEFT JOIN tblclients c ON s.customer_id = c.id
                  WHERE 1=1";

        $bindings = [];

        if (!empty($filters['status'])) {
            $query .= " AND s.status = ?";
            $bindings[] = $filters['status'];
        }

        if (!empty($filters['customer_id'])) {
            $query .= " AND s.customer_id = ?";
            $bindings[] = $filters['customer_id'];
        }

        $query .= " ORDER BY s.created_at DESC";

        $instances = $this->db->select($query, $bindings);

        return array_map(function($instance) {
            return [
                'id' => $instance->id,
                'customer_name' => $instance->customer_name,
                'instance_type' => $instance->instance_type,
                'status' => $instance->status,
                'max_bid_price' => $instance->max_bid_price,
                'interruption_count' => $instance->interruption_count,
                'created_at' => $instance->created_at
            ];
        }, $instances);
    }

    /**
     * Get savings report for spot usage
     */
    public function getSavingsReport(int $customerId, \DateTime $from, \DateTime $to): array {
        $spotUsage = $this->db->select(
            "SELECT SUM(uptime_hours) as total_hours,
                    SUM(on_demand_cost) as on_demand_cost,
                    SUM(spot_cost) as spot_cost
             FROM mod_spot_instances
             WHERE customer_id = ? AND created_at BETWEEN ? AND ?",
            [$customerId, $from->format('Y-m-d'), $to->format('Y-m-d')]
        )[0];

        $savings = $spotUsage->on_demand_cost - $spotUsage->spot_cost;
        $savingsPercent = $spotUsage->on_demand_cost > 0 ?
            ($savings / $spotUsage->on_demand_cost) * 100 : 0;

        return [
            'customer_id' => $customerId,
            'period' => ['from' => $from->format('Y-m-d'), 'to' => $to->format('Y-m-d')],
            'total_hours' => $spotUsage->total_hours,
            'on_demand_cost' => $spotUsage->on_demand_cost,
            'spot_cost' => $spotUsage->spot_cost,
            'total_savings' => $savings,
            'savings_percent' => round($savingsPercent, 2)
        ];
    }

    // Private helper methods

    private function submitSpotRequest(array $spotInstance): array {
        // Submit to cloud provider (AWS, GCP, Azure, etc.)
        // This is provider-specific implementation
        return ['success' => true, 'request_id' => 'spot-req-' . bin2hex(random_bytes(12))];
    }

    private function launchFallbackInstance(string $spotId): void {
        $spot = $this->getSpotInstance($spotId);

        // Launch on-demand instance as fallback
        $onDemandId = 'od_' . bin2hex(random_bytes(12));

        $this->db->insert('mod_ondemand_instances', [
            'id' => $onDemandId,
            'original_spot_id' => $spotId,
            'instance_type' => $spot['instance_type'],
            'region' => $spot['region'],
            'status' => 'launching'
        ]);

        // Trigger on-demand launch
    }
}

/**
 * Bidding Engine for Spot Instances
 */
class BiddingEngine {
    private $db;

    public function __construct() {
        $this->db = \WHMCS\Database\Capsule::connection();
    }

    public function calculateOptimalBid(string $instanceType, string $region): array {
        // Get historical prices
        $historicalPrices = $this->getHistoricalPrices($instanceType, $region);

        // Calculate statistics
        $avgPrice = array_sum($historicalPrices) / count($historicalPrices);
        $maxPrice = max($historicalPrices);
        $percentile70 = $this->calculatePercentile($historicalPrices, 70);
        $percentile90 = $this->calculatePercentile($historicalPrices, 90);

        // Determine optimal bid based on strategy
        $bidPrice = match($this->getStrategy()) {
            'low_cost' => $avgPrice * 0.8,
            'reliable' => $percentile70,
            'critical' => $percentile90,
            'optimal' => $avgPrice * 0.95,
            default => $avgPrice
        };

        return [
            'instance_type' => $instanceType,
            'region' => $region,
            'avg_price' => round($avgPrice, 4),
            'recommended_bid' => round($bidPrice, 4),
            'max_recommended' => round($maxPrice * 0.9, 4),
            'reliability_score' => $this->calculateReliabilityScore($historicalPrices)
       

---

*Content truncated.*

When not to use it

  • Mission-critical workloads without fallback plans
  • Environments without spot instance support

Prerequisites

WHMCS platformDatabase access

Limitations

  • Requires WHMCS module integration
  • Dependent on cloud provider spot availability

How it compares

It automates the complex logic of bidding and fallback that is typically handled manually in cloud consoles.

Compared to similar skills

whmcs-spot-instances side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
whmcs-spot-instances (this skill)02moNo flagsAdvanced
cloudflare-manager259moReviewIntermediate
railway-cli-management98moReviewIntermediate
azure-functions105moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

cloudflare-manager

qdhenry

Comprehensive Cloudflare account management for deploying Workers, KV Storage, R2, Pages, DNS, and Routes. Use when deploying cloudflare services, managing worker containers, configuring KV/R2 storage, or setting up DNS/routing. Requires CLOUDFLARE_API_KEY in .env and Bun runtime with dependencies installed.

25135

railway-cli-management

CaptainCrouton89

Deploy, manage services, view logs, and configure Railway infrastructure. Use when deploying to Railway, managing environment variables, viewing deployment logs, scaling services, or managing volumes.

9139

azure-functions

aj-geddes

Create serverless functions on Azure with triggers, bindings, authentication, and monitoring. Use for event-driven computing without managing infrastructure.

10104

nuxthub-migration

onmax

Use when migrating NuxtHub projects or when user mentions NuxtHub Admin sunset, GitHub Actions deployment removal, self-hosting NuxtHub, or upgrading to v1/nightly. Covers v0.9.X self-hosting (stable) and v1/nightly multi-cloud (experimental, database/blob not ready).

589

deployment-pipeline-design

wshobson

Design multi-stage CI/CD pipelines with approval gates, security checks, and deployment orchestration. Use when architecting deployment workflows, setting up continuous delivery, or implementing GitOps practices.

670

terraform-module-library

wshobson

Build reusable Terraform modules for AWS, Azure, and GCP infrastructure following infrastructure-as-code best practices. Use when creating infrastructure modules, standardizing cloud provisioning, or implementing reusable IaC components.

759

Search skills

Search the agent skills registry