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.zipInstalls 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 servicesKey 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
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
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.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| whmcs-spot-instances (this skill) | 0 | 2mo | No flags | Advanced |
| cloudflare-manager | 25 | 9mo | Review | Intermediate |
| railway-cli-management | 9 | 8mo | Review | Intermediate |
| azure-functions | 10 | 5mo | Review | Intermediate |
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.
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.
azure-functions
aj-geddes
Create serverless functions on Azure with triggers, bindings, authentication, and monitoring. Use for event-driven computing without managing infrastructure.
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).
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.
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.