Skip to main content

Audience Management

Overview

An audience is a target group used to aim campaign messages, bind a rich menu, or act as a trigger condition. The defining design decision is that audience members are stored as CSV files in object storage rather than as database rows, so an audience can scale to very large memberships. Reading the member list back therefore goes through the CSV Engine.

The module also runs a cron every minute to auto-refresh audiences configured for it, and keeps an audit log of members joining and leaving in the audience_member_log table.

Business Flow

Creating and viewing

  1. GET /api/audiences lists audiences with pagination.
  2. POST /api/audiences (multipart/form-data) creates an audience. The service first checks the plan's maxSegments quota; a duplicate name returns error AUD_001. The user either uploads a CSV or specifies filter criteria, after which the job is published to the create_audience queue for a worker to build the member file.
  3. GET /api/audiences/:id returns details — member count, criteria, and current status.
  4. GET /api/audiences/:id/member returns members with pagination, reading the CSV through the CSV Engine with a 30-second cache.
  5. PUT /api/audiences/:id updates an audience and publishes to the update_audience queue.
  6. DELETE /api/audiences/:id deletes one and publishes to the delete_audience queue.

Exporting

  1. GET /api/audiences/:id/export exports the member list as CSV, streamed directly into the response.
  2. GET /api/audiences/:id/export-detail exports with per-member detail. A failed export returns AUD_004; no members found returns AUD_005.

Auto-refresh

  1. PATCH /api/audiences/:id/auto-refresh enables or disables auto-refresh per audience. The organisation's plan must also grant the autoRefresh entitlement.
  2. The AudienceRefreshScheduler cron runs every minute on the * * * * * schedule, using a Redis lock so multiple replicas do not overlap. Audiences that are due are published to the audience_refresh queue.
  3. POST /api/audiences/:id/refresh triggers a manual refresh immediately, without waiting for the cron.

Tracking membership changes

  1. GET /api/audiences/:id/member-logs shows the history of members joining and leaving, drawn from audience_member_log.
  2. Those same joins and leaves are published as events to the audience_membership_trigger queue so Trigger Rule can act on them.

Key Files & Functions

Core code lives in internal/modules/audience/, comprising controller.go, service.go, scheduler.go, helpers.go, types.go, and dto.go, registered on the authed.Group("/audiences") group with modulegate.ModuleGate(d, "audiences").

MethodRouteHandlerPolicy (metadata)
GET/api/audiencessvc.getListHandlerreadAll audiences
GET/api/audiences/:idsvc.getByIDHandlerread audiences
GET/api/audiences/:id/membersvc.getMemberByAudienceIDHandlerread audiences
GET/api/audiences/:id/member-logssvc.getMemberLogsHandlerread audiences
GET/api/audiences/:id/exportsvc.getExportReportAllFriendHandlerexport audiences
GET/api/audiences/:id/export-detailsvc.exportMembersDetailHandlerexport audiences
POST/api/audiencessvc.createHandlercreate audiences
PUT/api/audiences/:idsvc.updateHandlerupdate audiences
PATCH/api/audiences/:id/auto-refreshsvc.updateAutoRefreshHandlerupdate audiences
POST/api/audiences/:id/refreshsvc.triggerManualRefreshHandlerupdate audiences
DELETE/api/audiences/:idsvc.deleteByIDHandlerdelete audiences

The scheduler is registered through audience.RegisterScheduler(d), which calls d.Scheduler.Register("* * * * *", "AudienceRefreshScheduler", s.handleAudienceRefresh). It is invoked both from RegisterRoutes and from registerSchedulers in cmd/api/modules.go.

Connections to Other Services

  • Access control — requests must pass ModuleGate("audiences"), with PolicyModuleAudiences as metadata.
  • Tablesaudience, audience_member_log, line_user, line_oa, api_client, organization
  • RabbitMQ — the create_audience, update_audience, delete_audience, audience_refresh, and audience_membership_trigger queues.
  • Redis — provides the refresh cron's lock, preventing overlapping runs across replicas.
  • Storage and CSV Engine — member files live on MinIO or S3 and are read back through the CSV Engine.
  • Cross-moduleplanlimits for the maxSegments quota and the autoRefresh entitlement, plus the apiclient module.
  • Error codesAUD_001 duplicate name, AUD_002 not an audience, AUD_003 invalid CSV, AUD_004 export failed, and AUD_005 LINE user not found.
  • Related modules — Audience Filter (which builds audiences from criteria), Campaign Management, Rich Menu, and Trigger Rule.