CoreAPI Development Guide
This guide covers the general workflows and what's needed for you to develop the CoreAPI backend.
Develop the backend and redeploy it with microservices
- Develop the code in your dedicated domain or package (e.g.
domain/commerce,domain/identity). - Use the corresponding
makecommands in theQuickstartdirectory to run your backend and the required microservices it depends on (Postgres, Redis, NATS, AuthAPI, Zitadel, etc.). - CoreAPI itself is orchestrated via
compose/services/CoreAPI.yml— you generally won't need to touch this unless you're changing how CoreAPI itself is built/run, not just the code inside it. - Each
maketarget maps to a specific combination of infra + services (see theMakefileat the root ofQuickstart). Pick the target that matches what you're actually working on rather than always reaching formake baseormake reset-all— this keeps rebuild times down and avoids spinning up services you don't need.
Example — working on a CoreAPI + Spatio (Malaysia ticketing) change:
Say you're editing something in domain/commerce and want to see it running
against the Malaysia/ticketing stack (CoreAPI + SpatioAdmin + TicketCMS):
# 1. Make your code change in CoreAPI
# e.g. edit domain/commerce/services/payment_service.go
# 2. From the Quickstart directory, bring up the matching stack
make malaysia
# this runs: $(INFRA) $(COREAPI) $(SPATIO) up --build -d
# → Postgres/Redis/Zitadel infra, CoreAPI (rebuilt from your change),
# SpatioAdmin, and TicketCMS
# 3. Test your change
curl -i http://localhost:3000/api/orderTicketGroup?id=test123
# or open SpatioAdmin/TicketCMS in the browser and exercise it manually
# 4. Tear it down when you're done
make malaysia-down # stop containers, keep volumes/data
make malaysia-down-v # stop containers AND wipe volumes (fresh DB next time)
The --build flag means make malaysia always rebuilds the CoreAPI image
from your current code before starting — you don't need a separate build
step. If you only changed CoreAPI code (not docker-compose/Dockerfile
config), this is usually all you need between edits: just re-run make
malaysia again.
Adding or configuring a microservice
- In the
Quickstartfolder, YAML files are already separated by concern for local development —compose/infrastructure/for shared infra (Postgres, Redis, NATS, Zitadel, SeaweedFS, CDN stack, etc.) andcompose/services/for the actual PlayTelly/CoreAPI-adjacent services (CoreAPI, PlayoutAdmin, TicketCMS, OrgConsole, etc.). Each is written the way you'd expect a normaldocker-composefile to look. - If you ever need a new microservice, add its YAML under the appropriate
compose/infrastructure/orcompose/services/folder, then map it into the rootMakefileso it's included in the relevantmaketarget. - Full detail on how the microservice orchestration itself works (compose file structure, networks/volumes, service dependencies) is covered in the separate Microservices Guide — this page intentionally doesn't go deep into that. That page also has an audit table of every current service's ports and env usage, worth checking before adding a new one so you don't collide with an existing port.
Adding a new environment variable
- You have two ways to add an environment variable:
- Shared
.env— if you're adding a variable for CoreAPI, use the shared.envfile at the root ofQuickstart. This is the suggested default, since most CoreAPI-related services already read from it viaenv_file: - ../../.env(routing up from the compose subfolder to the root.env). - Directly in the YAML file — you can also declare the variable
inline under a service's
environment:block, as seen in some YAML files (e.g.pgadmin's config below). This is more common for service-specific values that don't need to be shared or overridden per environment.
services:
postgres:
image: postgres:16-alpine
networks:
- internal
ports:
- '5432:5432'
env_file:
- ../../.env
volumes:
- postgres_data:/var/lib/postgresql/data
- ./postgres-init:/docker-entrypoint-initdb.d
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER"]
interval: 20s
timeout: 20s
retries: 5
pgadmin:
image: dpage/pgadmin4
networks:
- internal
environment:
PGADMIN_DEFAULT_EMAIL: admin@local.dev
PGADMIN_DEFAULT_PASSWORD: admin
PGADMIN_CONFIG_SERVER_MODE: "False"
PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False"
volumes:
- ./pgadmin/pgadmin-servers.json:/pgadmin4/servers.json
ports:
- "5050:80"
depends_on:
postgres:
condition: service_healthy
restart: unless-stopped