DOCUMENTATION

StreamSource docs

Everything you need to build, deploy and run real-time pipelines on StreamSource, from your first sandbox pipeline to production in your own cloud.

Version 1.0Updated October 2026
GETTING STARTED

Introduction

StreamSource is a Kafka-based streaming platform that you deploy into your own AWS, GCP or Azure account. It bundles managed Kafka, a connector catalog, no-code and custom transforms, a schema registry, autoscaling and monitoring, and lets you control all of it from one dashboard or the ssctl CLI.

Your data stays in your account. Our control tower only sends deployment instructions and receives health metrics. Message payloads never pass through StreamSource servers.

GETTING STARTED

Quickstart

This guide builds a small pipeline in the free sandbox: sample GPS devices flow through a geofence, and alerts go to a webhook. No cloud account or credit card is needed.

Install the CLI

You can do everything below from the dashboard. The CLI is shown because it's easier to copy.

bash
$ curl -fsSL https://get.streamsource.dev/ssctl | sh
$ ssctl login
$ ssctl workspace use sandbox

Build the pipeline

  1. Add a sourceThe sandbox comes with a demo-gps source that writes to sandbox.raw.gps. Check it is running:
    bash
    $ ssctl component get demo-gps
    NAME      KIND    STATUS   OUT
    demo-gps  source  Running  sandbox.raw.gps
  2. Add a geofence transformIt reads positions and writes an event whenever a vehicle enters or leaves the polygon.
    bash
    $ ssctl component create depot-fence \
        --type transform/geofence \
        --in sandbox.raw.gps --out sandbox.evt.fence \
        --set zones=@depot.geojson
  3. Send alerts to a webhookUse any URL that accepts a POST, such as a test endpoint.
    bash
    $ ssctl component create alerts-hook \
        --type sink/webhook --in sandbox.evt.fence \
        --set url=https://example.com/hooks/fleet
  4. Watch it runOpen Pipelines in the dashboard to see the canvas, or tail the topic:
    bash
    $ ssctl topic tail sandbox.evt.fence --limit 5
✓
That's a working pipeline. Nothing here is sandbox-specific. When you connect your own cloud, the same commands work against your cluster.
GETTING STARTED

Core concepts

StreamSource has a small model. Once these five ideas are clear, everything else follows.

Workspace

An isolated space for one team or project. Each workspace gets its own topics, Kafka users and permissions, so components in one workspace cannot read another workspace's data.

Components

Everything you deploy is a component, and there are three kinds:

SourceBrings data inDevice TCP/UDP, MQTT, HTTP, database change capture, files in object storage.
TransformChanges itReads one or more topics and writes one or more topics. No-code or custom.
SinkSends it outPostgres, S3, BigQuery, Elasticsearch, queues, webhooks and more.
ConnectorThe templateA connector is an installable component type from the catalog. Deploying one creates a component.

Topics connect everything

Components never call each other. They only read and write Kafka topics. The pipeline is not stored anywhere. If component A writes topic T and component B reads topic T, the canvas draws A → B. There is no workflow engine or scheduler in the data path, so adding or replacing a component never needs a redeploy of the others.

Environment

A Kubernetes cluster running StreamSource in a specific cloud account and region, such as prod-india on AWS ap-south-1. One environment can hold many workspaces.

BUILD PIPELINES

Sources

A source brings data from outside into a topic. Pick one from the connector catalog, fill in its settings form, and choose the topic it writes to.

Device gateways

Telematics devices such as Teltonika and iTriangle connect over TCP to a native gateway. The gateway decodes nothing on the hot path: it writes each frame as-is to a raw topic, keyed by device ID, and a decoder transform turns it into typed events.

component.yaml
name: teltonika-tcp
type: source/teltonika
replicas: 2
config:
  port: 5027
  codecs: [8, 8E, 16]
outputs:
  - fleet.raw.teltonika
i
Acknowledgements are safe. A source only sends an ACK to the device (or HTTP 2xx, or MQTT PUBACK) after Kafka has confirmed the write. If the outcome is unknown, the device retries and the event ID removes the duplicate later.

Database change capture

PostgreSQL, MySQL, MongoDB and SQL Server sources run on Kafka Connect. They read the database log, so they add no query load to your primary. Each change's log position becomes its event ID.

BUILD PIPELINES

Transforms

Transforms read from topics, change the data and write to topics. Most needs are covered by no-code transforms that you configure in the dashboard.

TransformWhat it does
filterKeeps or drops events based on field conditions, for example spd > 80.
mapRenames, casts, drops and computes fields.
splitSends matching events to one topic and the rest to another. Rules can change without stopping the pipeline.
enrichAdds fields from a reference table or a state topic.
geofenceEmits enter and exit events for polygons and circles.
alertFires when a condition holds for a set duration, per device or key.

How commits work

A transform only commits its input offset after every output record, or its dead-letter record, has been stored by Kafka. If a transform emits several records from one input, each gets the ID <input id>/<n>.

BUILD PIPELINES

Custom code

When no-code transforms aren't enough, write your own in Python, Go, Node or Java. Connect a Git repository or use the browser editor. StreamSource builds an image, versions it and deploys it like any other component.

harsh_braking.py
from streamsource import transform

@transform(src="fleet.evt.position", dst="fleet.evt.alerts")
def harsh_braking(event, state):
    prev = state.get(event.key)
    state[event.key] = event.value
    if prev and prev["spd"] - event.value["spd"] > 30:
        yield {"type": "harsh_braking", **event.value}

Bring a container

Any container that reads or writes Kafka can become a component. Add a connector.yaml with a JSON Schema for its settings, and StreamSource generates the form, stores secrets in your cloud's secret manager and scales it on consumer lag.

!
Keep the event ID. If your code passes an event through unchanged, keep its ce_id header. Sinks use it to drop duplicates.
BUILD PIPELINES

Sinks

A sink reads topics and writes to an external system: a database, warehouse, object store, queue or HTTP endpoint.

Sinks only commit their offset after the external write succeeds. Writes are idempotent, keyed on (workspace, ce_id), so a retry after a crash updates the same row instead of adding a second one.

bash
$ ssctl component create pg-positions \
    --type sink/postgres --in fleet.evt.position \
    --set table=positions --set batch.size=500 \
    --secret dsn=pg-prod-dsn
BUILD PIPELINES

Topics and naming

Every topic follows one pattern: <workspace>.<stage>.<name>. The stage tells you what the topic holds and how long it keeps data.

StageHoldsCleanupExample
rawBytes exactly as receivedDelete after retentionfleet.raw.teltonika
evtTyped, schema-checked eventsDelete after retentionfleet.evt.position
stateLatest value per keyCompactedfleet.state.position-latest
dlqFailed records with the reasonDelete after retentionfleet.dlq.decoder

Partitions and ordering

The record key is the ordering key, such as a device ID. Order is guaranteed only per key. Adding partitions to a keyed topic changes which partition a key lands on, so StreamSource refuses to increase partitions on a keyed topic unless you pass --allow-key-remap.

BUILD PIPELINES

Schemas

Every evt topic has a registered schema. StreamSource ships a schema registry with a Confluent-compatible API, so standard Kafka clients work unchanged.

  • Formats: Protobuf for platform schemas. JSON Schema for your own schemas, because it's easier to start with.
  • Compatibility: BACKWARD by default. A change that would break existing consumers is rejected when you register it.
  • Domain packs: packs such as Mobility ship their schemas, for example mobility.position.v1.
RUN IN PRODUCTION

Deploy to your cloud

In production, StreamSource runs in your own cloud account. After a one-time setup, every supported operation runs from the dashboard. You only open your cloud console for billing, account settings or emergency recovery.

Setup on AWS

  1. SubscribeFind StreamSource in AWS Marketplace, or start from Settings → Environments → Connect cloud.
  2. Grant accessLaunch the CloudFormation stack. It creates one cross-account IAM role, limited to resources tagged streamsource:managed.
  3. ProvisionPick a region. StreamSource creates an EKS cluster, Kafka, the schema registry and the agent. This takes about 25 minutes.
  4. BuildThe environment appears as Healthy in the dashboard. Deploy your first source.

GCP uses a Terraform module with a service account, and Azure uses an ARM template with a managed identity. The steps are otherwise the same.

How the agent connects

The agent inside your cluster enrolls once with a single-use token, then uses short-lived certificates that rotate automatically. It opens an outbound mTLS connection to our control tower, so you don't expose any inbound port. It can only deploy workloads from an approved list.

i
If our control tower is down, your pipelines keep running. Data never depends on us. You can't deploy from the dashboard until it's back, but ssctl still works directly against your cluster.
RUN IN PRODUCTION

Delivery guarantees

StreamSource delivers at least once, with stable event IDs so that downstream systems can remove duplicates. A crash or network failure can cause a repeat, never a silent gap.

Event headers

Every record carries these headers, following the CloudEvents Kafka binding. The payload stays untouched in the message value.

HeaderMeaning
ce_idStable event ID, kept through every transform that doesn't split or merge events.
ce_sourceThe producing component, as <workspace>/<component>.
ce_typeEvent type, for example mobility.position.
ce_timeWhen the event happened, as reported by the origin (RFC 3339, UTC).
ingest_timeWhen StreamSource first received it.
content_typeapplication/x-protobuf, application/json or application/octet-stream.
schema_idSchema registry ID, on typed topics.

How event IDs are made

  • Devices: source:device:sequence when the protocol has a sequence number, otherwise a hash of the frame plus the record index.
  • HTTP and MQTT: the client's idempotency key when present.
  • Database CDC: the log position (LSN or binlog offset).

A timestamp alone is never used as an event ID.

RUN IN PRODUCTION

Monitoring and dead letters

Each component reports throughput, consumer lag, error rate and dead-letter count. Grafana dashboards and Prometheus metrics come preconfigured in every environment, and components scale out automatically when their lag grows.

Replaying dead letters

When a record can't be processed, it goes to the component's dlq topic with the error attached. Fix the cause, then replay:

bash
$ ssctl dlq list fleet.dlq.decoder --since 1h
$ ssctl dlq replay fleet.dlq.decoder --to fleet.raw.teltonika --since 1h
RUN IN PRODUCTION

Roles and access

Roles are set per workspace. Sign in with Google, Microsoft or email. Every change is recorded in an audit log that you can export.

RoleCan
AdminEverything, including members, billing and cloud settings.
MaintainerDeploy and change connectors, transforms and topics.
DeveloperWrite and test custom code and SQL queries.
ViewerSee pipelines and dashboards. Can't change anything.
REFERENCE

ssctl CLI

Everything in the dashboard is available from ssctl. Commands act on the current workspace unless you pass --workspace.

CommandWhat it does
ssctl loginSigns in through your browser and stores a short-lived token.
ssctl workspace use <name>Sets the current workspace.
ssctl component create <name>Deploys a component. Use --type, --in, --out, --set and --secret.
ssctl component apply -f file.yamlCreates or updates components from YAML. Good for CI.
ssctl component get [name]Lists components and their status.
ssctl graphPrints the pipeline as derived from topics.
ssctl topic tail <topic>Streams recent messages from a topic.
ssctl dlq replay <topic>Sends dead-lettered records back for processing.
ssctl env listLists environments, their cloud, region and version.
REFERENCE

REST API

The REST API is what the dashboard and ssctl use. Authenticate with a workspace API token in the Authorization: Bearer header.

MethodPathPurpose
GET/v1/workspaces/{ws}/componentsList components
POST/v1/workspaces/{ws}/componentsCreate a component
PATCH/v1/workspaces/{ws}/components/{name}Change settings or replicas
DELETE/v1/workspaces/{ws}/components/{name}Remove a component
GET/v1/workspaces/{ws}/graphPipeline graph derived from topics
GET/v1/connectorsConnector catalog with config schemas
bash
$ curl https://api.streamsource.dev/v1/workspaces/fleet/components \
    -H "Authorization: Bearer $SS_TOKEN"
REFERENCE

Limits and defaults

SettingSandboxYour cloud
Throughput1 MB/sDepends on cluster size
Retention24 hoursYou choose, per topic
Components5No limit
Replication factor13, with min.insync.replicas=2
Producer settingsacks=all, idempotence on, unclean leader election off
!
Plan retention for disk. 10,000 events/s at 500 bytes is about 432 GB a day, or roughly 9 TB for 7 days at replication factor 3. The pricing page has a planner for this.
HELP

Troubleshooting

A component's lag keeps growing

Check its error rate first. If errors are low, it needs more replicas or the topic needs more partitions. Autoscaling can't add replicas beyond the topic's partition count.

I see duplicate rows in my database

Duplicates are expected under at-least-once delivery. Make sure your sink writes upserts keyed on ce_id, and that custom code keeps the ID when it passes events through.

My schema change was rejected

Under BACKWARD compatibility you can add optional fields but not remove or rename required ones. Create a new versioned type, such as .v2, for breaking changes.

HELP

Get support

Sandbox users can ask in the community forum. Team and Enterprise customers can raise a ticket from Help → Support in the dashboard, or reach us through the contact page.

Was this page helpful?