Sync Scheduler
Coming Q1 2026 — This feature is in development.
Request early access to be notified when available.
Overview
Orbital nodes can only sync with ground during ground station passes. The Sync Scheduler optimizes data transfer across these limited windows, ensuring critical updates are prioritized and bandwidth is fully utilized.
Key Components
SyncScheduler Main scheduler for pass planning
GroundStation Ground station configuration
PriorityQueue Bandwidth-aware priority queuing
SyncWindow Pass window with bandwidth estimate
The Synchronization Challenge
Ground station passes are intermittent - each satellite only has line-of-sight to a ground station for a portion of each orbit.
Ground Station Location Typical Pass Pattern Svalbard 78°N 8-10 passes/day, 10-15 min each Singapore 1°N 4-6 passes/day, 8-12 min each
Combined coverage from multiple ground stations reduces gaps but doesn’t eliminate them. The Sync Scheduler optimizes data transfer across these limited windows.
Ground Station Configuration
from rotastellar_distributed import SyncScheduler, GroundStation
# Define your ground stations
stations = [
GroundStation(
name = "svalbard" ,
lat = 78.2 ,
lon = 15.6 ,
bandwidth = 1e9 , # 1 Gbps
elevation_min = 10 # Minimum elevation angle
),
GroundStation(
name = "singapore" ,
lat = 1.3 ,
lon = 103.8 ,
bandwidth = 500e6 # 500 Mbps
),
GroundStation(
name = "santiago" ,
lat =- 33.4 ,
lon =- 70.6 ,
bandwidth = 500e6
)
]
# Initialize scheduler
scheduler = SyncScheduler(
api_key = "rs_..." ,
ground_stations = stations,
orbital_nodes = [ "orbital-1" , "orbital-2" , "orbital-3" ]
)
Getting Sync Windows
Query upcoming sync opportunities:
from datetime import datetime, timedelta
# Get next 24 hours of sync windows
windows = scheduler.get_windows( hours = 24 )
for window in windows:
print ( f "Node: { window.orbital_node } " )
print ( f "Station: { window.ground_station } " )
print ( f "Start: { window.start } " )
print ( f "Duration: { window.duration_seconds } s" )
print ( f "Max elevation: { window.max_elevation } °" )
print ( f "Bandwidth: { window.bandwidth / 1e6 :.0f} Mbps" )
print ( f "Capacity: { window.capacity_mb :.0f} MB" )
print ()
# Filter for specific node
orbital_1_windows = scheduler.get_windows(
hours = 24 ,
node = "orbital-1"
)
# Filter for specific station
svalbard_windows = scheduler.get_windows(
hours = 24 ,
station = "svalbard"
)
Scheduling Sync Operations
Schedule data transfers with priority:
from datetime import datetime, timedelta
# Schedule a sync operation
sync = scheduler.schedule_sync(
node = "orbital-1" ,
data_size = 50e6 , # 50 MB
priority = "critical" , # "critical", "high", "normal", "low"
deadline = datetime.now() + timedelta( hours = 2 ),
data_type = "gradients"
)
print ( f "Sync ID: { sync.id } " )
print ( f "Scheduled window: { sync.window.start } " )
print ( f "Estimated completion: { sync.estimated_completion } " )
# Schedule multiple operations
syncs = scheduler.schedule_batch([
{ "node" : "orbital-1" , "data_size" : 50e6 , "priority" : "critical" },
{ "node" : "orbital-2" , "data_size" : 30e6 , "priority" : "high" },
{ "node" : "orbital-3" , "data_size" : 100e6 , "priority" : "normal" },
])
Priority Queue
The scheduler maintains a priority queue for each orbital node:
# View queue for a node
queue = scheduler.get_queue( "orbital-1" )
for item in queue.items:
print ( f "ID: { item.id } " )
print ( f "Priority: { item.priority } " )
print ( f "Size: { item.data_size / 1e6 :.1f} MB" )
print ( f "Deadline: { item.deadline } " )
print ( f "Status: { item.status } " )
print ()
# Queue statistics
print ( f "Total queued: { queue.total_size / 1e6 :.1f} MB" )
print ( f "Critical items: { queue.critical_count } " )
print ( f "Estimated clear time: { queue.estimated_clear_time } " )
Priority Levels
Priority Description Preemption criticalSafety-critical or time-sensitive Preempts all others highImportant updates (e.g., model weights) Preempts normal/low normalStandard sync (e.g., gradients) No preemption lowBackground sync (e.g., telemetry) Fills unused capacity
Optimization
Optimize sync schedule across all nodes and stations:
# Generate optimized schedule
plan = scheduler.optimize(
horizon_hours = 24 ,
objectives = {
"minimize_latency" : 0.5 , # Weight for latency
"maximize_throughput" : 0.3 , # Weight for throughput
"balance_load" : 0.2 # Weight for load balancing
}
)
print ( f "Scheduled { len (plan.operations) } sync operations" )
print ( f "Total data: { plan.total_data_mb :.0f} MB" )
print ( f "Bandwidth utilization: { plan.utilization :.1%} " )
print ( f "Average wait time: { plan.avg_wait_minutes :.1f} min" )
# View schedule
for op in plan.operations:
print ( f " { op.time } : { op.node } → { op.station } ( { op.data_mb :.0f} MB)" )
# Apply the optimized schedule
scheduler.apply(plan)
Monitoring
Track sync operations in real-time:
# Get current sync status
status = scheduler.get_status()
print ( f "Active syncs: { status.active_count } " )
print ( f "Queued: { status.queued_count } " )
print ( f "Completed (24h): { status.completed_24h } " )
print ( f "Failed (24h): { status.failed_24h } " )
# Monitor specific operation
sync_status = scheduler.get_sync_status(sync_id)
print ( f "Progress: { sync_status.progress :.1%} " )
print ( f "Bytes transferred: { sync_status.bytes_transferred } " )
print ( f "Current rate: { sync_status.rate_mbps :.1f} Mbps" )
# Set up callbacks
@scheduler.on_sync_complete
def handle_complete ( sync ):
print ( f "Sync { sync.id } completed: { sync.data_size / 1e6 :.1f} MB" )
@scheduler.on_sync_failed
def handle_failed ( sync , error ):
print ( f "Sync { sync.id } failed: { error } " )
# Auto-reschedule critical syncs
if sync.priority == "critical" :
scheduler.reschedule(sync.id)
Example: 24-Hour Sync Plan
from rotastellar_distributed import SyncScheduler, GroundStation
# Setup
scheduler = SyncScheduler(
api_key = "rs_..." ,
ground_stations = [
GroundStation( "svalbard" , lat = 78.2 , lon = 15.6 , bandwidth = 1e9 ),
GroundStation( "singapore" , lat = 1.3 , lon = 103.8 , bandwidth = 500e6 ),
GroundStation( "chile" , lat =- 33.4 , lon =- 70.6 , bandwidth = 500e6 ),
],
orbital_nodes = [ "sat-1" , "sat-2" , "sat-3" , "sat-4" , "sat-5" ]
)
# Queue gradient syncs for all nodes
for i in range ( 1 , 6 ):
scheduler.schedule_sync(
node = f "sat- { i } " ,
data_size = 100e6 , # 100 MB gradients per node
priority = "high" ,
data_type = "gradients"
)
# Optimize
plan = scheduler.optimize( horizon_hours = 24 )
# Results:
# - 5 nodes × 100 MB = 500 MB total
# - 12 ground passes utilized
# - Average wait time: 45 minutes
# - Bandwidth utilization: 78%
# - All syncs complete within 6 hours
Next Steps