Getting Started
This track is the recommended path for anyone new to Stem. Follow the pages in order—each builds on the previous one and links to deeper references when you want to explore further.
- Introduction – Prerequisites, the feature tour, and how the onboarding journey is structured.
- Quick Start – Create your first Stem tasks, enqueue with delays/priorities, and inspect results in memory.
- First Steps – Run a worker against Redis, enqueue from a producer, and read results.
- Connect to Infrastructure – Run Redis/Postgres locally, configure brokers/backends, experiment with routing and canvas patterns.
- Observe & Operate – Enable OpenTelemetry export, inspect workers/queues/DLQ via CLI, and wire lifecycle signals.
- Prepare for Production – Apply signing/TLS, deploy with systemd or CLI multi-process tooling, and run quality gates before launch.
- Troubleshooting – Common errors and quick fixes while onboarding.
- Stem vs BullMQ – Canonical feature mapping with
✓/~ /✗parity semantics.
Once you complete the journey, continue with the in-depth material under Core Concepts and Workers.
Preview: a full Stem pipeline in one file
Use this example as a mental model for how tasks, workers, and brokers fit together.
- Define the task handler
- Configure retries and rate limits
- Create the broker, backend, and worker
- Start the worker and enqueue tasks
stem_example.dart
static final definition = TaskDefinition<HelloArgs, void>(
name: 'demo.hello',
encodeArgs: (args) => {'name': args.name},
metadata: TaskMetadata(description: 'Simple hello world example'),
);
String get name => 'demo.hello';
TaskMetadata get metadata => definition.metadata;
stem_example.dart
TaskOptions get options => const TaskOptions(
queue: 'default',
maxRetries: 3,
rateLimit: '10/s',
visibilityTimeout: Duration(seconds: 60),
);
stem_example.dart
final registry = SimpleTaskRegistry()..register(HelloTask());
final broker = await RedisStreamsBroker.connect('redis://localhost:6379');
final backend = await RedisResultBackend.connect('redis://localhost:6379/1');
final stem = Stem(broker: broker, registry: registry, backend: backend);
final worker = Worker(broker: broker, registry: registry, backend: backend);
stem_example.dart
unawaited(worker.start());
// Map-based enqueue for quick scripts or one-off calls.
await stem.enqueue('demo.hello', args: {'name': 'Stem'});
// Typed helper with TaskDefinition for compile-time safety.
await stem.enqueueCall(HelloTask.definition(const HelloArgs(name: 'Stem')));
await Future<void>.delayed(const Duration(seconds: 1));
await worker.shutdown();
await broker.close();
await backend.close();