Skip to main content

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 StationLocationTypical Pass Pattern
Svalbard78°N8-10 passes/day, 10-15 min each
Singapore1°N4-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

PriorityDescriptionPreemption
criticalSafety-critical or time-sensitivePreempts 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