The Sticker Award Service manages sticker assignments to users in the Stickerlandia platform. It provides:
- Assignment API (
/api/awards/v1/assignments) - User sticker assignment management (CRUD operations) - Event Integration - Publishes sticker assignment events as stickers are assigned, reacts to events elsewhere in the system (e.g., when a user is created)
Transport-Agnostic Messaging: The service supports multiple messaging transports (Kafka, AWS EventBridge/SQS) via runtime configuration. Business handlers remain transport-agnostic by working only with CloudEvents - they never interact with Kafka or AWS-specific message formats.
Middleware Pattern: Message processing follows a consistent pipeline regardless of transport:
- Transport layer receives raw message (Kafka
ConsumerMessageor AWSSQSMessage) - Middleware wrapper extracts Datadog trace context and DSM checkpoints
- Middleware parses CloudEvent from message body
- Business handler receives typed
CloudEvent[T]and executes domain logic
Steps 1-3 are provider specific, step 4 is generic across providers.
Factory Selection: The handler factory selects the appropriate middleware implementation based on configuration (MESSAGING_PROVIDER=kafka|aws)
graph TB
subgraph "Message Flow"
A[Transport Consumer<br/>Kafka/SQS] -->|Raw Message| B[Middleware Wrapper]
B -->|1. Extract DSM/Trace| C[DSM Checkpoint]
B -->|2. Parse CloudEvent| D[Business Handler]
D -->|Typed CloudEvent<T>| E[Domain Logic]
end
subgraph "Factory Pattern"
F[Config: MESSAGING_PROVIDER] -->|kafka| G[Kafka Middleware]
F -->|aws| H[AWS Middleware]
G --> B
H --> B
end
subgraph "Business Layer"
E --> I[Repository]
E --> J[External APIs]
E --> K[Event Publisher]
end
style D fill:#e1f5ff
style E fill:#e1f5ff
Messaging Abstractions (internal/messaging/)
EventPublisher- Publishes domain events (Kafka or EventBridge)MessageConsumer- Consumes messages (Kafka consumer group or SQS)CloudEventMessageHandler[T]- Shared interface for business handlersfactory/- Creates transport-specific consumers, producers, handlers
Middleware (internal/messaging/{kafka,aws}/middleware.go)
- Wraps business handlers with DSM tracking, tracing, CloudEvent parsing
- Creates root traces with span links for distributed tracing
- Injects Datadog headers for cross-service correlation
Domain (internal/domain/)
- Entities, repository interfaces, business rules
- No dependencies on transport or infrastructure
Technology Stack
- Go 1.23+, Gin, PostgreSQL, GORM, Viper
- Messaging: Kafka (sarama) or AWS SDK v2
- Datadog: dd-trace-go for APM and DSM
- CloudEvents 1.0 for event schema
GET /api/awards/v1/assignments/{userId}- Get user's sticker assignmentsPOST /api/awards/v1/assignments/{userId}- Assign a sticker to a userDELETE /api/awards/v1/assignments/{userId}/{stickerId}- Remove sticker assignment
GET /health- Health check with database connectivity
Full API documentation is available in OpenAPI format:
- Synchronous API: api.yaml
- Asynchronous API: async_api.json
- Go 1.23+
- PostgreSQL 15+
- Apache Kafka (for event publishing)
- Docker & Docker Compose (for local development)
Run the full development stack:
docker-compose up --buildRun locally (requires separate PostgreSQL):
make run
# or
go run ./cmd/serverRun all unit tests:
make testRun all tests, including integration tests:
make test-integrationRun tests with coverage:
make test-coverageBuild the application:
make buildBuild Docker image:
make docker-build# Format code
make fmt
# Run linter
make lintThe service is configured via environment variables:
SERVER_PORT- HTTP server port (default: 8080)
DATABASE_HOST- Database host (default: localhost)DATABASE_PORT- Database port (default: 5432)DATABASE_USER- Database user (default: sticker_user)DATABASE_PASSWORD- Database passwordDATABASE_NAME- Database name (default: sticker_awards)DATABASE_SSL_MODE- SSL mode (default: disable)
STICKER_CATALOGUE_BASE_URL- Catalogue service URL
MESSAGING_PROVIDER- Messaging transport (kafka or aws, default: kafka)
KAFKA_BROKERS- Kafka broker addresses (comma-separated)KAFKA_GROUP_ID- Consumer group IDKAFKA_PRODUCER_TIMEOUT- Producer timeout in milliseconds (default: 5000)KAFKA_PRODUCER_RETRIES- Number of retry attempts (default: 3)KAFKA_PRODUCER_BATCH_SIZE- Batch size in bytes (default: 16384)KAFKA_REQUIRE_ACKS- Acknowledgment level (default: 1)KAFKA_ENABLE_IDEMPOTENT- Enable idempotent producer (default: true)
AWS_REGION- AWS region (default: us-east-1)AWS_EVENTBRIDGE_BUS_NAME- EventBridge bus name (required)AWS_SQS_QUEUE_URL- SQS queue URL (required)AWS_MAX_CONCURRENCY- Max concurrent message processors (default: 10)AWS_VISIBILITY_TIMEOUT- SQS visibility timeout in seconds (default: 30)AWS_WAIT_TIME_SECONDS- SQS long polling duration in seconds (default: 20)- AWS credentials via standard AWS SDK chain (environment variables, IAM role, etc.)
LOG_LEVEL- Log level (debug, info, warn, error)LOG_FORMAT- Log format (json, console)
The sticker award service can be deployed to AWS, Azure & GCP. For deployment instructions see cloud provider specific instructions below:
AWS deployment uses the AWS CDK. Inside the CDK code, there is the concept of an 'integrated' (dev, prod) and 'non-integrated' environment. For developing a development instance of the sticker award service you'll first need to copy some parameters inside AWS, and then deploy using the below commands.
The service expects SSM parameters named:
- /stickerlandia//sticker-award/database-host
- /stickerlandia//sticker-award/database-name
- /stickerlandia//sticker-award/database-user
- /stickerlandia//sticker-award/database-password
- /stickerlandia//sticker-award/kafka-broker
- /stickerlandia//sticker-award/kafka-username
- /stickerlandia//sticker-award/kafka-password
You will need to create those before running the deploy commands below.
export ENV= # The environment name to use, don't use 'dev' or 'prod'. Your initials is normally a good start.
export VERSION= # The commit hash you want to use, defaults to latest
export DD_API_KEY= # The Datadog API key for your org
export DD_SITE = # The Datadog site to use
cd infra/aws
cdk deploy