Skip to main contentUkasyah Nata Dewastoro
On-prem

SAS Viya 3.5 platform with an N-node database cluster and Kafka ingestion

A multi-machine SAS Viya 3.5 deployment with no single point of failure: one writable PostgreSQL primary with N hot standbys behind pgpool-II, an odd-N Consul quorum, and Kafka topics loaded into CAS through SAS Event Stream Processing, so any single tier can fail without losing records.

1 writer, N standbys
Role
Infrastructure engineer
Scale
N hosts, N-node data cluster, N partitions per topic
Stack
SAS Viya 3.5, Ansible, Viya-ARK
Targets
No single point of failure, replayable ingestion

Context

SAS Viya 3.5 runs as a set of N hosts across several tiers: coordination, data, microservices, HTTP proxies, CAS compute, and an ingestion tier fed from Kafka. The goal is a layout where any single host or tier can fail and the platform recovers without data loss and without anyone choosing between two writers.

Constraints:

  • One logical database shared by all microservices
  • Consul is required before any service starts
  • Records arrive continuously and must not be lost or applied twice
  • On-prem only; no managed services

Architecture and failover

Users reach the platform through a load balancer and N HTTP proxies, which forward to N microservice hosts. Every microservice stores its state in one logical database through the data tier below.

The data tier is the platform's SAS Infrastructure Data Server. Node 0 is the single writable primary. Nodes 1 to N are hot standbys on streaming replication. N pgpool-II instances sit in front, with a watchdog virtual IP held by one of them. Microservices connect only to the virtual IP, never to a node.

Consul runs as an odd N servers on the microservice hosts, with a client agent on every other host. Vault runs beside them and must be registered before pgpool starts. RabbitMQ runs as an N-node cluster for service messaging.

Analytics compute is a CAS grid: one controller and N workers. Streaming data arrives from Kafka topics with N partitions each. SAS Event Stream Processing reads the topics and loads the CAS grid, so the stream does not touch the database path.

The failover scenarios below use illustrative timings. Counts are shown as N throughout.

SAS Viya 3.5 multi-machine platform topologyUsers reach a load balancer, then N HTTP proxies and N microservice hosts. Microservices use the SAS Infrastructure Data Server through pgpool-II: one primary and N hot standbys. Consul and Vault coordinate every host. Kafka topics are consumed by SAS Event Stream Processing, which loads the CAS grid.Outside the platformViya services, N hostsSAS Infrastructure Data ServerconfigstreamingtopicsloadLoad balancerclient entryKafka topicsN brokersSAS ESPKafka connectorConsul + Vaultquorum N of NHTTP proxyhttpd × NMicroservicesN hostsCAS grid1 controller + N workersRabbitMQN-node clusterpgpool-II × Nvirtual IP on oneData node 0primaryData node 1hot standbyData node Nhot standby
  • Primary / serving
  • Recovering
  • Degraded
  • Down
  • Replication / control

Pick a failure to see how the system detects and recovers from it.

Key decisions

One primary and N hot standbys behind pgpool-II

  • PostgreSQL
  • HA
  • database

All platform microservices share one logical database, so the data tier needs automatic failover without ever allowing two writers.

  • Separate write and read instancesNot supported by the platform; services share one logical database.
  • External managed PostgreSQLMore topology control, but the team then owns HA, backup and upgrades outside the vendor lifecycle.
  • Native data server: 1 primary + N standbys + pgpoolChosenStreaming replication, one writer, a watchdog virtual IP and vendor-supported lifecycle.

Trade-off: Write capacity is limited to a single primary; standbys add availability and read capacity, not write scale.

Lifecycle

  1. Define the inventory groups for each tier and the per-host variables for the data nodes and pgpool instances.
  2. Run the playbooks from the single controller. Start Consul servers and Vault first, then Consul agents on every other host.
  3. Start the data tier in order: consul-template services, node 0 as primary, standbys gated on a standby configuration file, then pgpool.
  4. Start RabbitMQ, the HTTP proxies, CAS and the remaining microservices, then the Event Stream Processing project.
  5. Verify before declaring done: every Consul member alive, one leader, N backends up in pgpool, replication streaming at equal positions.

Failure modes

FailureBlast radiusDetectionRecovery
Primary data node lostWrites pause briefly; service calls retrypgpool health checkAutomatic promotion of a standby; clients reconnect through the virtual IP
Standby lostReduced read capacity and redundancyReplication and pgpool stateRebuild or restart as standby
One Consul server lostNone while a quorum remainsMember and leader checksRestart the server; quorum returns to N
Consul quorum lostNo service start, no config renderingLeader check on serversRestore a majority of servers
pgpool instance lostVirtual IP movesWatchdogAutomatic; no client reconfiguration
CAS worker lostReduced capacity; running actions may failController worker stateRedundant table copies rebalance; rerun failed actions, replace the worker
Kafka broker lostPartition leadership movesBroker and under-replicated partition alertsAutomatic leader election; replace the broker
Controller host lostNo changes possible, runtime unaffectedBackup and host monitoringRestore the controller from backup

Results

1writable primary at any time, never two
Nhot standbys on streaming replication
(N-1)/2Consul servers that can fail without losing quorum
0records lost: Kafka retains them until loaded

What I'd change

I would pair every service-wrapper status with a real health check: Consul membership queried on a server, pgpool backend state, and replication position. A wrapper that only inspects a process or PID file can report a healthy database as stopped.

I would put the Consul servers and the data nodes on separate failure domains from the start, and add the VIP address to the database certificate names so clients that connect by address verify cleanly.

I would also size Kafka retention against the longest recovery window and make every load into CAS safe to replay from day one.