Bidirectional Sync

Outpost acts as a hub for bidirectional synchronization between your support tickets and external issue trackers. Changes flow in both directions — updates in Outpost propagate to the tracker, and changes in the tracker propagate back to Outpost.

How It Works

The sync system uses an adapter plugin pattern. Each external tracker (GitHub Issues, Linear, etc.) has a dedicated sync adapter that knows how to:

Architecture

sync architecture diagram
                        ┌─────────────────────┐
                        │   External Tracker   │
                        │  (GitHub / Linear)   │
                        └─────────┬───────────┘
                                  │
                         webhooks │ ▲ API calls
                                  ▼ │
                        ┌─────────────────────┐
                        │    Sync Adapter      │
                        │  (per-tracker plugin)│
                        └─────────┬───────────┘
                                  │
                       map fields │ ▲ map fields
                                  ▼ │
                        ┌─────────────────────┐
                        │    SyncEngine         │
                        │  (orchestrator)      │
                        └─────────┬───────────┘
                                  │
                          read/write │
                                  ▼
                        ┌─────────────────────┐
                        │  Outpost Database    │
                        │  (tickets, messages) │
                        └─────────────────────┘

The SyncEngine is the orchestrator that coordinates all sync operations. It processes incoming webhook events from trackers, applies field mappings, and writes changes to the Outpost database. When Outpost tickets change, the SyncEngine notifies the appropriate adapter to push updates back to the external tracker.

Adapter Plugin Pattern

Each sync adapter implements a standard interface that the SyncEngine calls. This makes it straightforward to add support for new trackers without modifying the core sync logic. An adapter is responsible for:

  1. Field mapping — translating between the tracker's data model and Outpost's ticket model (status, priority, assignee, labels)
  2. Webhook handling — parsing incoming webhook payloads from the tracker and converting them to Outpost-compatible change events
  3. Outbound sync — pushing Outpost ticket changes to the tracker's API
  4. Identity mapping — associating tracker user accounts with Outpost TeamMembers
  5. Bulk import — importing existing issues from the tracker into Outpost on initial setup

What Syncs

The following fields are synchronized bidirectionally:

FieldOutpost → TrackerTracker → Outpost
StatusMapped via status mapping configMapped via status mapping config
PriorityMapped to tracker priority levelsMapped to Outpost priority levels
AssigneeMapped via identity mappingMapped via identity mapping
Labels / TagsApplied as tracker labelsApplied as Outpost tags
CommentsPosted as tracker commentsAdded as ticket messages
TitleUpdated in trackerUpdated in Outpost

Conflict Resolution

When the same field is changed on both sides between sync cycles, Outpost uses a last-write-wins strategy based on timestamps. Each sync event carries a timestamp, and the most recent change takes precedence. Conflict events are logged for audit purposes.

Supported Trackers

TrackerStatusDocs
GitHub Issues Built-in (via GitHub App) GitHub App Setup
Linear Available Linear Integration

Adding more trackers: The adapter pattern makes it straightforward to add support for Jira, Asana, or any other issue tracker. See the Contributing guide for details on implementing a new sync adapter.