Skip to content

SMS Router Configuration

This reference covers properties consumed by sms-router-service. Installation commands and shared infrastructure are documented in bare-metal installation and Docker deployments.

Runtime and service discovery

Property Default Environment Description
server.port 0 base; 9015 dev SERVER_PORT HTTP port used by the service. The main configuration lets the system choose a port, while the development profile uses port 9015. Docker health checks also use 9015.
server.shutdown graceful SERVER_SHUTDOWN Controls how the service stops. graceful waits for current HTTP requests to finish when the process receives SIGTERM.
spring.profiles.active dev ACTIVE_PROFILE or SPRING_PROFILES_ACTIVE Selects the active Spring profile. The default is dev.
spring.application.name sms-router-service SPRING_APPLICATION_NAME Service name used by Spring, Eureka, and load balancing.
spring.lifecycle.timeout-per-shutdown-phase 30s SPRING_LIFECYCLE_TIMEOUT_PER_SHUTDOWN_PHASE Maximum time allowed for each clean shutdown phase.
spring.task.scheduling.pool.size 4 SCHEDULING_POOL_SIZE Number of threads shared by campaign, outbox, recovery, and cleanup jobs.
eureka.client.service-url.defaultZone http://localhost:8761/eureka/ EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE URL of the Eureka server used for service registration and discovery.
eureka.instance.prefer-ip-address true EUREKA_INSTANCE_PREFER_IP_ADDRESS Controls whether Eureka registers the service by IP address or hostname. true uses the IP address; false uses the hostname.

The router finds client-service through Eureka. It waits up to 5 seconds to connect and 10 seconds for a response. These timeouts are set in code and cannot be changed through configuration.

Security and actuator

Property Default Environment Description
admin.api.key empty ADMIN_API_KEY Shared key required for /admin/**, /internal/**, protected actuator endpoints, and router requests to client-service. If the value is empty, all these requests fail authentication.
server.servlet.context-path empty SERVER_SERVLET_CONTEXT_PATH Optional path added before every service endpoint. The actuator security filter also uses this path.
management.endpoints.web.base-path /actuator MANAGEMENT_ENDPOINTS_WEB_BASE_PATH Main URL path for actuator endpoints and health checks.
management.endpoints.web.exposure.include health,info,metrics,scheduledtasks,loggers,threaddump,env,configprops,flyway MANAGEMENT_ENDPOINTS_WEB_EXPOSURE_INCLUDE Lists the actuator endpoints available over HTTP. heapdump is not included.
management.endpoint.health.probes.enabled true MANAGEMENT_ENDPOINT_HEALTH_PROBES_ENABLED Turns liveness and readiness health checks on or off. true enables both health groups.
management.endpoint.health.show-details always MANAGEMENT_ENDPOINT_HEALTH_SHOW_DETAILS Controls when full health details are shown. The default always shows them, so the admin key must protect the combined health endpoint.

The public paths are /actuator/health/liveness, /actuator/health/readiness, and /actuator/info. The combined /actuator/health endpoint and all other actuator endpoints require the admin key. Do not disable Spring Security for actuator paths. The firewall and security filters protect these endpoints.

Database, Flyway, and connection pool

Property Default Environment Description
spring.datasource.url jdbc:postgresql://localhost:5432/sms_gateway?currentSchema=sms_router DB_URL JDBC URL used to connect to the sms_router PostgreSQL schema.
spring.datasource.username appuser DB_USERNAME Username used to connect to PostgreSQL.
spring.datasource.password apppass DB_PASSWORD Password used to connect to PostgreSQL. Replace the development value outside local development.
spring.datasource.hikari.maximum-pool-size 10 SPRING_DATASOURCE_HIKARI_MAXIMUM_POOL_SIZE Maximum number of database connections in the pool. Account for both API requests and scheduled jobs when setting this value.
spring.datasource.hikari.minimum-idle 2 SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE Minimum number of unused database connections kept ready.
spring.datasource.hikari.connection-timeout 30000 ms SPRING_DATASOURCE_HIKARI_CONNECTION_TIMEOUT Maximum time to wait for a database connection from the pool.
spring.datasource.hikari.idle-timeout 600000 ms SPRING_DATASOURCE_HIKARI_IDLE_TIMEOUT Time an unused connection can remain in the pool before it is removed.
spring.datasource.hikari.max-lifetime 1800000 ms SPRING_DATASOURCE_HIKARI_MAX_LIFETIME Maximum time a connection can stay in the pool. Keep it shorter than the timeout used by the database or network.
spring.jpa.hibernate.ddl-auto validate SPRING_JPA_HIBERNATE_DDL_AUTO Controls how Hibernate handles the database schema. validate checks the Flyway-managed schema without changing it. Do not use update in production.
spring.jpa.properties.hibernate.default_schema sms_router SPRING_JPA_PROPERTIES_HIBERNATE_DEFAULT_SCHEMA PostgreSQL schema used by JPA and Hibernate.
spring.jpa.open-in-view false SPRING_JPA_OPEN_IN_VIEW Controls whether a database session stays open while an HTTP response is created. Keep this false so sessions close at transaction boundaries.
spring.flyway.enabled true SPRING_FLYWAY_ENABLED Controls whether Flyway updates the database schema at startup.
spring.flyway.baseline-on-migrate true SPRING_FLYWAY_BASELINE_ON_MIGRATE Allows Flyway to create a starting version for an existing schema without migration history. Review this setting carefully for a new production database.
spring.flyway.baseline-version 0 SPRING_FLYWAY_BASELINE_VERSION Starting migration version used when Flyway creates a baseline.
spring.flyway.schemas / default-schema sms_router SPRING_FLYWAY_SCHEMAS, SPRING_FLYWAY_DEFAULT_SCHEMA Schemas that Flyway manages and uses by default.
spring.flyway.url/user/password datasource-equivalent DB_URL, DB_USERNAME, DB_PASSWORD Database connection values used by Flyway when it runs migrations.

Kafka producer and outbox

Property Default Environment Description
spring.kafka.bootstrap-servers localhost:9092 KAFKA_BOOTSTRAP_SERVERS Comma-separated Kafka broker addresses used for the first connection.
spring.kafka.producer.acks all SPRING_KAFKA_PRODUCER_ACKS Controls how many broker confirmations are required. all waits for all current topic copies to confirm the message.
spring.kafka.producer.retries 5 SPRING_KAFKA_PRODUCER_RETRIES Number of times the Kafka client retries a failed send. This is separate from the application's outbox retries.
spring.kafka.producer.properties.enable.idempotence true SPRING_KAFKA_PRODUCER_PROPERTIES_ENABLE_IDEMPOTENCE Prevents the Kafka producer from creating duplicate messages during supported retries.
outbox.publisher.enabled true OUTBOX_PUBLISHER_ENABLED Controls whether this service publishes pending outbox rows to Kafka. false leaves new rows waiting in the outbox.
outbox.publisher.poll-ms 500 ms OUTBOX_PUBLISHER_POLL_MS Delay after one outbox publishing run finishes before the next run starts.
outbox.publisher.batch-size 50 OUTBOX_PUBLISHER_BATCH_SIZE Maximum number of outbox rows claimed in one publishing run.
outbox.publisher.send-timeout-ms 5000 ms OUTBOX_PUBLISHER_SEND_TIMEOUT_MS Maximum time to wait for all Kafka sends started by one batch.
outbox.recovery.enabled true OUTBOX_RECOVERY_ENABLED Controls whether failed outbox rows are moved back to pending for another attempt.
outbox.recovery.poll-ms 60000 ms OUTBOX_RECOVERY_POLL_MS Delay between checks for failed outbox rows that can be retried.
outbox.recovery.max-rounds 3 OUTBOX_RECOVERY_MAX_ROUNDS Maximum number of times a failed row can be moved back to pending.
outbox.recovery.cooldown-minutes 5 OUTBOX_RECOVERY_COOLDOWN_MINUTES Minimum time a failed row must wait before it can be retried.
outbox.recovery.batch-size 100 OUTBOX_RECOVERY_BATCH_SIZE Maximum number of failed rows moved back to pending in one run.

Disabling the publisher does not disable campaign creation or direct acceptance. Requests continue writing outbox rows, so queue depth grows until a publisher-enabled instance resumes draining them.

Multipart and bulk build

Property Default Environment Description
spring.servlet.multipart.max-file-size 64MB SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE Maximum size of an uploaded CSV file.
spring.servlet.multipart.max-request-size 64MB SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE Maximum size of the full upload request, including the file and other fields.
campaign.bulk.max-recipients 1000000 CAMPAIGN_BULK_MAX_RECIPIENTS Maximum number of valid recipients accepted from one CSV file.
campaign.bulk.build.enabled true CAMPAIGN_BULK_BUILD_ENABLED Controls whether this service can claim and process uploaded campaign files.
campaign.bulk.build.poll-ms 2000 ms CAMPAIGN_BULK_BUILD_POLL_MS Delay after one campaign build check finishes before the next check starts.
campaign.bulk.build.batch-size 1 CAMPAIGN_BULK_BUILD_BATCH_SIZE Maximum number of uploaded files claimed in one build run.
campaign.bulk.build.chunk-size 1000 CAMPAIGN_BULK_BUILD_CHUNK_SIZE Number of recipients validated, priced, and saved at a time.
campaign.bulk.build.stale-minutes 30 CAMPAIGN_BULK_BUILD_STALE_MINUTES Time an upload can remain IN_PROGRESS before another worker can claim it.
campaign.bulk.build.silent-claim-warn-ms 60000 ms CAMPAIGN_BULK_BUILD_SILENT_CLAIM_WARN_MS Minimum time between warnings when queued work cannot be claimed.

The original CSV file is stored in PostgreSQL. Plan database storage, PostgreSQL write-ahead log (WAL) space, and request memory for files up to the 64 MB HTTP limit.

Campaign schedule and regulatory window

Property Default Environment Description
campaign.schedule.min-lead-seconds 60 CAMPAIGN_SCHEDULE_MIN_LEAD_SECONDS Minimum number of seconds between creating a scheduled campaign and its start time.
campaign.schedule.max-future-days 90 CAMPAIGN_SCHEDULE_MAX_FUTURE_DAYS Maximum number of days in the future that a campaign can be scheduled.
campaign.schedule.deadline-grace-minutes 60 CAMPAIGN_SCHEDULE_DEADLINE_GRACE_MINUTES Extra time allowed after the scheduled start. The campaign expires at scheduledAt plus this value.
campaign.btrc.enabled true BTRC_ENABLED or CAMPAIGN_BTRC_ENABLED Controls whether the BTRC promotional sending window is enforced. Disable it only in a controlled non-production environment.
campaign.btrc.zone-id Asia/Dhaka BTRC_ZONE_ID or CAMPAIGN_BTRC_ZONE_ID Time zone used to check campaign schedules and sending hours.
campaign.btrc.window.start-hour 9 BTRC_WINDOW_START_HOUR First allowed sending hour. The hour is included in the allowed window.
campaign.btrc.window.end-hour 24 BTRC_WINDOW_END_HOUR Hour when sending must stop. The hour is not included; 24 means the end of the day.

Changing the window affects new campaigns, rescheduled campaigns, and checks made when messages are sent. It does not change existing scheduled times.

Dispatcher, DLR roll-up, and retry

Property Default Environment Description
campaign.dispatcher.enabled true CAMPAIGN_DISPATCHER_ENABLED Controls whether this service can claim campaigns and send their recipients for processing.
campaign.dispatcher.poll-ms 1000 ms CAMPAIGN_DISPATCHER_POLL_MS Delay after one campaign dispatch run finishes before the next run starts.
campaign.dispatcher.campaign-batch-size 10 CAMPAIGN_DISPATCHER_CAMPAIGN_BATCH_SIZE Maximum number of campaigns claimed in one dispatch run.
campaign.dispatcher.recipient-batch-size 999 CAMPAIGN_DISPATCHER_RECIPIENT_BATCH_SIZE Maximum number of recipients claimed for one campaign transaction. The default matches the promotional MNPSP limit.
campaign.rollup.enabled true CAMPAIGN_ROLLUP_ENABLED Controls whether SMS recipient delivery results are copied to campaign recipient records.
campaign.rollup.poll-ms 2000 ms CAMPAIGN_ROLLUP_POLL_MS Delay after one delivery-result update run finishes before the next run starts.
campaign.rollup.batch-size 1000 CAMPAIGN_ROLLUP_BATCH_SIZE Maximum number of recipient records updated in one run.
campaign.retry.enabled true CAMPAIGN_RETRY_ENABLED Controls whether recipients with temporary failures are made ready for another attempt.
campaign.retry.poll-ms 5000 ms CAMPAIGN_RETRY_POLL_MS Delay between checks for recipients that are ready to retry.
campaign.retry.batch-size 200 CAMPAIGN_RETRY_BATCH_SIZE Maximum number of recipients made ready again in one run.
campaign.refund-retry.enabled true CAMPAIGN_REFUND_RETRY_ENABLED Controls whether the service retries refunds that have not been confirmed for recipients in a final state.
campaign.refund-retry.poll-ms 30000 ms CAMPAIGN_REFUND_RETRY_POLL_MS Delay between checks for refunds that are ready to retry.
campaign.refund-retry.batch-size 100 CAMPAIGN_REFUND_RETRY_BATCH_SIZE Maximum number of refunds claimed in one retry run.
campaign.refund-retry.cooldown-minutes 5 CAMPAIGN_REFUND_RETRY_COOLDOWN_MINUTES Minimum time a failed refund must wait before another attempt.

Message speed depends on polling delays, batch sizes, available database connections, Kafka response time, and provider limits. Change one setting at a time. Monitor queued work, processing time, database connection use, and provider rate limits after each change.

Stale recovery, idempotency, and scheduler health

Property Default Environment Description
campaign.stale.enabled true CAMPAIGN_STALE_ENABLED Controls whether the service finds and repairs campaigns that are stuck in an unfinished state.
campaign.stale.poll-ms 60000 ms CAMPAIGN_STALE_POLL_MS Delay between checks for stuck campaign work.
campaign.stale.dispatch-grace-minutes 10 CAMPAIGN_STALE_DISPATCH_GRACE_MINUTES Time a dispatch can remain unchanged before the service tries to recover it.
campaign.stale.cancelling-grace-minutes 10 CAMPAIGN_STALE_CANCELLING_GRACE_MINUTES Time a campaign can remain in CANCELLING before the service tries to finish the cancellation.
campaign.stale.cancelling-batch-size 50 CAMPAIGN_STALE_CANCELLING_BATCH_SIZE Maximum number of stuck cancellations handled in one recovery run.
campaign.stale.draft-grace-minutes 15 CAMPAIGN_STALE_DRAFT_GRACE_MINUTES Time a campaign can remain in DRAFT before its reserved balance is reversed and the campaign is marked as failed.
campaign.stale.draft-batch-size 50 CAMPAIGN_STALE_DRAFT_BATCH_SIZE Maximum number of stuck draft campaigns handled in one recovery run.
campaign.stale.building-grace-minutes 45 CAMPAIGN_STALE_BUILDING_GRACE_MINUTES Time a campaign can remain in BUILDING before recovery starts. Keep this longer than the build reclaim time.
campaign.stale.building-batch-size 50 CAMPAIGN_STALE_BUILDING_BATCH_SIZE Maximum number of stuck campaign builds handled in one recovery run.
idempotency.purge.enabled true IDEMPOTENCY_PURGE_ENABLED Controls whether expired request replay records are deleted.
idempotency.purge.poll-ms 3600000 ms IDEMPOTENCY_PURGE_POLL_MS Delay between cleanup runs. The replay period is fixed in code at 24 hours.
scheduler.health.startup-grace-seconds 180 SCHEDULER_HEALTH_STARTUP_GRACE_SECONDS Time after startup when missing scheduler locks do not make the health check fail.

Set building-grace-minutes higher than campaign.bulk.build.stale-minutes. Otherwise, recovery can fail a build before another builder is allowed to claim it.

Encryption and caches

Property Default Environment Description
jasypt.encryptor.password dev-only-jasypt-master-key JASYPT_ENCRYPTOR_PASSWORD Master password used to encrypt and decrypt configuration and database values. Replace the development value outside local development.
jasypt.encryptor.algorithm PBEWITHHMACSHA512ANDAES_256 JASYPT_ENCRYPTOR_ALGORITHM Algorithm used to encrypt and decrypt protected values.
jasypt.encryptor.iv-generator-classname org.jasypt.iv.RandomIvGenerator JASYPT_ENCRYPTOR_IV_GENERATOR_CLASSNAME Class that creates a random initialization vector for each encrypted value.

Routing caches can hold up to 5,000 entries for ten minutes. The client DLR setting uses a separate cache that holds up to 10,000 clients for 60 seconds. If the router cannot load a client's configuration, it does not cache the failure and keeps DLR enabled for safety.