How It Works: Architecture

A technical reference for how the Outstand social media API aggregator works: the ingest → normalize → per-platform adaptor → send fan-out pipeline, synchronous vs asynchronous posting, queuing and backpressure, partial-success semantics, rate limiting, and retries.

Outstand is a social media API aggregator: you integrate once against a single API, and Outstand fans each request out to every downstream social platform (X, LinkedIn, Instagram, Facebook, TikTok, YouTube, Threads, Pinterest, Bluesky, Google Business, and more). This page explains the architecture — how a single create post call becomes many platform-specific publishes — so you can reason about latency, consistency, and failure handling in your integration.

What "aggregator" means here

A social media API aggregator collapses N platform integrations into one. Instead of learning ten OAuth flows, ten payload formats, ten media-upload dances, and ten rate-limit regimes, you send one normalized request to Outstand. Outstand owns the per-platform translation and delivery.

The core of the system is a fan-out pipeline: one inbound post is duplicated, adapted, and dispatched to each connected account independently. The rest of this document walks that pipeline stage by stage.

The Fan-Out Pipeline

Every publish moves through four stages:

ingest  ─▶  normalize  ─▶  per-platform adaptor  ─▶  send

1. Ingest

The client sends a single normalized request to the API gateway, which routes /v1/posts to the posts API handler. The handler validates the payload, then persists three things transactionally:

  • The post record (content-level metadata, scheduledAt).
  • One or more post containers — the normalized content units (text + attached media) that make up the post.
  • The post-to-account links — the set of connected social accounts this post should fan out to.

At this point nothing has been sent to any platform. Ingest is intentionally cheap: its job is to durably record intent and hand off to the pipeline. The API responds immediately with a post ID (see the Synchronous vs Asynchronous section below).

2. Normalize

Normalization is what makes "integrate once" possible. Your inbound content is stored in a platform-agnostic representation — a post container holding text and an ordered list of media references. This canonical form is deliberately independent of any single platform's schema.

When publishing runs, the publishing service loads the post, its containers, and the list of target accounts, producing an in-memory normalized object that each adaptor consumes. Media is stored once and referenced by every account's adaptor rather than re-uploaded per request by the client.

3. Per-Platform Adaptor

Each connected account maps to a provider adaptor selected by network. Conceptually:

adaptor      = selectAdaptor(account.network)
platformPostId = adaptor.publish(normalizedPost, account)

The adaptor is the per-platform translation layer. It takes the normalized post and turns it into exactly what that platform's API expects — the correct field names, media-upload sequence (e.g. Instagram's container-creation-then-poll, X's chunked media upload), character constraints, and authentication. Every adaptor implements the same contract: it receives all the parameters it needs and never touches the database or other platforms directly. This isolation is why one platform's quirks or outages can't corrupt another's publish.

Immediately before an adaptor sends, the pipeline ensures the account's access token is valid, refreshing short-lived tokens on demand (TikTok tokens, for example, last only ~24h and are refreshed inline before the send).

4. Send

The adaptor calls the platform's API and returns a platform post ID on success. The pipeline then records the outcome per account:

  • Successstatus: published, platformPostId populated, publishedAt set. The first success also stamps the post-level publishedAt.
  • Failurestatus: failed, error populated with the platform's message.

Crucially, each account is sent independently and a failure does not abort the others — see the Partial-Success Semantics section below.

Synchronous vs Asynchronous Posting

Outstand's publish path is asynchronous by design.

AspectBehavior
API call (POST /v1/posts)Synchronous — validates, persists, enqueues, and returns a post ID within milliseconds.
Actual publishing to platformsAsynchronous — performed later by the publishing service, decoupled via a queue.
Immediate posts (no scheduledAt)Enqueued with a scheduleTime of now; publishing typically begins within seconds.
Scheduled posts (scheduledAt set)Enqueued with scheduleTime = scheduledAt; the queue holds the task until then (±30s).

This split matters for your integration: a 200 from POST /v1/posts means "accepted and durably queued", not "live on every platform." To learn the actual per-account outcome you either poll GET /v1/posts/{id} or, preferably, subscribe to webhooks. See the Post Lifecycle guide for the status fields.

Why asynchronous? Publishing to a single platform can take anywhere from ~1s to ~10s (media upload, container polling, third-party latency). A post fanning out to eight accounts could otherwise block the client for a minute or more and would be at the mercy of the slowest platform. Decoupling ingest from send keeps the client-facing API fast and predictable while absorbing downstream variability.

Queuing and Backpressure

The decoupling between ingest and send is provided by a managed task queue. Ingest enqueues one publishing task per post; a separate queue handles webhook delivery.

The queue does three jobs:

  1. Time-shifting. Each task carries a scheduleTime. Immediate posts run now; scheduled posts are held by the queue until their moment. No cron-polling loop is required.
  2. Backpressure. The queue enforces dispatch limits — maximum dispatches per second and maximum concurrent in-flight tasks. During a spike (say, thousands of scheduled posts firing at the top of the hour), tasks queue up and drain at a controlled rate instead of overwhelming the publishing service or the downstream platform APIs. Producers (the ingest path) never block on consumers.
  3. Durability. An enqueued task survives service restarts and transient outages. If the publishing service is briefly unavailable, the queue holds and redelivers.

Because backpressure lives in the queue rather than in the client-facing API, your POST /v1/posts latency stays flat even when the system is draining a large scheduled backlog.

Partial-Success Semantics

Multi-platform fan-out is not all-or-nothing. Each account in a post is published independently, and the pipeline deliberately continues past failures:

for account in post.accounts:
    try:
        platformPostId = adaptor(account).publish(normalizedPost, account)
        markPublished(account, platformPostId)
    catch error:
        markFailed(account, error)
        # continue to the next account instead of aborting the batch

This yields three possible post-level outcomes:

OutcomeConditionPost-level effectWebhook
Full successEvery account publishedpublishedAt setpost.published
Partial successSome published, some failedpublishedAt set (first success)post.published (payload lists both)
Full failureEvery account failedpublishedAt stays nullpost.error

The single post.published event fires when at least one account succeeds; its payload enumerates every account with either a platformPostId (success) or an error (failure), so a partial outcome is fully observable in one notification. post.error fires only when the entire fan-out failed.

Integration implication: always inspect per-account status rather than treating the post as a single boolean. A post that "published" may still have a failed account — for example an expired Facebook token — while its other accounts went live. See Post Lifecycle for the exact fields.

Rate Limiting and Retries

Rate limiting and retries operate at two layers, which together protect both Outstand and the downstream platforms.

Queue-level (transport)

The task queue applies its own retry policy to each publishing and webhook task. If a task's handler returns a retryable failure, the queue re-dispatches it with exponential backoff up to a configured maximum, without any client involvement. Combined with the dispatch-rate and concurrency caps described under Queuing and Backpressure above, this smooths bursts so downstream platform APIs are approached at a sustainable rate rather than in a thundering herd.

Adaptor-level (platform)

Individual adaptors handle platform-specific timing directly. Where a platform requires an asynchronous publish (e.g. Instagram and X media containers), the adaptor polls the platform for readiness with bounded attempts before completing the send. When a platform returns a rate-limit or auth error, the adaptor surfaces a structured error (rate_limited, unauthorized, forbidden, network_error) that is recorded on the account and reflected in the health-check surface.

What retries mean for you

  • Transient transport failures (cold start, brief network blip) are retried automatically by the queue — you don't need to resubmit.
  • Terminal platform failures (invalid media, expired token, content rejected) are recorded as failed on that account and are not silently retried into a duplicate post. To republish after fixing the cause, delete the failed post and create a new one — see the retry guidance in Post Lifecycle.
  • Idempotency: because a successful send records the account as published, re-publishing logic keys off per-account status to avoid double-posting to a platform that already succeeded.

Performance and SLA Implications

A few properties fall out of this architecture that are worth designing around:

  • API responsiveness is decoupled from platform latency. POST /v1/posts returns in milliseconds regardless of how many platforms the post targets or how slow they are, because the send happens off the request path.
  • End-to-end publish time is bounded by the slowest platform in the fan-out, plus queue dispatch delay. Accounts within a post are processed one after another, so a post with many accounts, or one that includes a slow media upload, takes proportionally longer to fully go live. Budget seconds, not milliseconds, for full fan-out completion.
  • Scheduled accuracy is approximately ±30 seconds of scheduledAt, governed by queue dispatch timing.
  • Spikes degrade gracefully, not catastrophically. Backpressure means a large simultaneous scheduled batch drains at a controlled rate; individual posts may see slightly higher queue latency under load, but the ingest API and unrelated traffic are unaffected.
  • Failure is isolated. A single platform outage or a single expired token affects only that account's send, never the post as a whole and never other accounts.

For real-time confirmation of when content actually goes live, rely on webhooks rather than the synchronous API response; for after-the-fact inspection, poll GET /v1/posts/{id}.

Summary

ConcernHow Outstand handles it
One integration, many platformsNormalized request → per-platform adaptors
Client latencySynchronous ingest, asynchronous send
SchedulingscheduleTime on queued tasks
Load spikesQueue backpressure (rate + concurrency caps)
Multi-platform failuresIndependent per-account send, partial success
Transient errorsAutomatic queue retries with backoff
Platform-specific timingAdaptor-level polling and structured errors
ObservabilityPer-account status + post.published / post.error webhooks