# Gas Station reference

This reference describes the configuration and deployment parameters for the Gas Station Service.

This applies to on-premise deployments only. For SaaS deployments, the Gas Station Service is managed by Ripple.

## Prerequisites

Before deploying the Gas Station Service, ensure you have:

- A running Ripple Custody environment
- Kubernetes cluster (1.21+)
- Helm (3.0+)
- PostgreSQL database (13+)


## Configuration parameters

Configure the Gas Station Service using environment variables or Helm values:

| Parameter | Description | Default | Required |
|  --- | --- | --- | --- |
| `GATEWAY_SERVER_URL` | Ripple Custody API gateway URL | — | Yes |
| `PRIVATE_KEY` | Bot user private key (PEM format) | — | Yes |
| `POLLING_INTERVAL_MS` | Interval for checking pending transactions (milliseconds) | `5000` | No |
| `MAX_RETRY_ATTEMPTS` | Maximum immediate retry attempts for failed funding | `3` | No |
| `RETRY_INTERVAL_MINUTES` | Interval between queue-based retries | `5` | No |
| `FEE_SAFETY_MARGIN_PERCENT` | Safety margin added to estimated fees | `10` | No |
| `POSTGRES_URL` | PostgreSQL connection string | — | Yes |
| `LOG_LEVEL` | Logging verbosity (debug, info, warn, error) | `info` | No |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OpenTelemetry collector endpoint | — | No |


## Helm values

Create a values file for the Gas Station Helm chart:


```yaml
gasStation:
  enabled: true
  gatewayUrl: "https://your-custody-gateway.example.com"
  pollingIntervalMs: 5000
  maxRetryAttempts: 3
  retryIntervalMinutes: 5
  feeSafetyMarginPercent: 10
  
  database:
    host: "postgres.example.com"
    port: 5432
    name: "gas_station"
    username: "gas_station_user"
    existingSecret: "gas-station-db-credentials"
    
  credentials:
    existingSecret: "gas-station-credentials"
    privateKeyKey: "private-key"
    
  telemetry:
    enabled: true
    otlpEndpoint: "http://otel-collector:4317"
```

## Database setup

The Gas Station Service requires a PostgreSQL database for event deduplication and failed job tracking.

### Create the database


```sql
CREATE DATABASE gas_station;
CREATE USER gas_station_user WITH ENCRYPTED PASSWORD 'your-secure-password';
GRANT ALL PRIVILEGES ON DATABASE gas_station TO gas_station_user;
```

### Database schema

The service automatically creates the following tables on startup:

| Table | Purpose |
|  --- | --- |
| `processed_event` | Event deduplication and distributed locking |
| `failed_funding_job` | Failed funding attempts for queue-based retry |
| `dead_letter_queue` | Permanently failed jobs requiring manual intervention |
| `sponsor` | Sponsorship configuration |
| `alert` | Low-balance alert thresholds |
| `event` | Audit trail for configuration changes |


#### ProcessedEvent table

Serves as both event deduplication log and distributed lock mechanism. The UNIQUE constraint on `id` prevents duplicate event processing across multiple service instances.

| Column | Type | Description |
|  --- | --- | --- |
| `id` | UUID | Event ID from Ripple Custody (primary key, provides distributed lock) |
| `locked_at` | TIMESTAMP | When lock was acquired (for stale lock detection) |
| `transaction_order_id` | UUID | Transaction order ID for idempotency tracking |
| `created_at` | TIMESTAMP | When event was first detected |
| `processed_at` | TIMESTAMP | When processing completed successfully |
| `status` | VARCHAR(20) | Processing status: `processing` or `completed` |


Locks older than 10 minutes are considered stale (crashed worker). The service automatically releases stale locks and retries processing.

#### FailedFundingJob table

Stores failed funding attempts for background retry processing.

| Column | Type | Description |
|  --- | --- | --- |
| `id` | UUID | Unique job identifier |
| `event_id` | UUID | Reference to Ripple Custody event ID |
| `account_id` | UUID | Account that needs funding |
| `sponsor_id` | UUID | Sponsor account providing funds |
| `required_amount` | VARCHAR(100) | Amount needed (string to preserve precision) |
| `ticker_id` | UUID | Token/ticker UUID for the native token |
| `created_at` | TIMESTAMP | When job was created |
| `retry_count` | INTEGER | Number of retry attempts |
| `next_retry_at` | TIMESTAMP | When job should be retried next |


#### DeadLetterQueue table

Stores funding jobs that have permanently failed after exhausting all retry attempts.

| Column | Type | Description |
|  --- | --- | --- |
| `id` | UUID | Unique identifier |
| `event_id` | UUID | Original Ripple Custody event ID |
| `account_id` | UUID | Account that needed funding |
| `sponsor_id` | UUID | Sponsor account that was attempted |
| `required_amount` | VARCHAR(100) | Amount that was needed |
| `ticker_id` | UUID | Token/ticker UUID |
| `original_error_message` | TEXT | Last error message before failure |
| `final_retry_count` | INTEGER | Number of retry attempts before giving up |
| `failed_at` | TIMESTAMP | When job was moved to dead letter queue |


Jobs in the dead letter queue require manual investigation. Set up alerts to monitor for new entries in this table.

## Security considerations

### Private key protection

- Store the bot user's private key in a secrets management solution (Kubernetes Secrets, HashiCorp Vault, AWS Secrets Manager)
- Never commit private keys to version control
- Rotate keys periodically according to your security policy


### Access control

- Restrict database access to the Gas Station Service only
- Use network policies to limit communication between services
- Enable TLS for all connections (database, API gateway, telemetry)


### Audit logging

- Enable audit logging in Ripple Custody to track all bot user actions
- Forward Gas Station logs to your SIEM for security monitoring
- Set up alerts for unusual funding patterns


## Monitoring and observability

The Gas Station Service exports metrics and traces via OpenTelemetry.

### Gauges (current state)

| Metric | Description |
|  --- | --- |
| `failed_jobs_queue_size` | Number of jobs in FailedFundingJob table |
| `processed_events_count` | Number of rows in ProcessedEvent table (for cleanup monitoring) |
| `sponsor_balance_<ticker>` | Current balance of each sponsor account |


### Counters (cumulative)

| Metric | Description |
|  --- | --- |
| `funding_attempts_total{status, chain}` | Total funding attempts by status (`success`/`failed`) and chain (e.g., `eth`) |
| `events_processed_total{outcome}` | Events processed by outcome (`funded`/`skipped`/`failed`) |
| `retry_attempts_total{attempt}` | Distribution of retry attempts (1, 2, or 3) before success/failure |


### Histograms (distributions)

| Metric | Description |
|  --- | --- |
| `funding_duration_seconds` | Time from event detection to funding completion |
| `job_age_at_success_hours` | How long jobs were in queue before succeeding |
| `api_latency_seconds{endpoint}` | Ripple Custody API latencies (`dry_run`/`submit_intent`/`get_balance`) |


For telemetry configuration, see [Telemetry overview](/products/custody/v1.34/deployment/reference/telemetry).

## Health check endpoints

The Gas Station Service exposes health check endpoints for Kubernetes liveness and readiness probes:

| Endpoint | Purpose | Description |
|  --- | --- | --- |
| `/health` | Liveness probe | Checks if the service is running and responsive |
| `/ready` | Readiness probe | Verifies database connectivity and Ripple Custody API reachability |


### Configure Kubernetes probes


```yaml
livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 30

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10
```

These endpoints enable proper orchestration, zero-downtime deployments, and automatic service recovery.

## Related documentation

| Topic | Description |
|  --- | --- |
| [Gas Station concepts](/products/custody/v1.34/concepts/gas-station) | Sponsorship hierarchy and multi-chain support |
| [Configure bot users](/products/custody/v1.34/api/environment/user/bot-user) | Set up bot users for automated operations |
| [Configure gas sponsorship](/products/custody/v1.34/api/accounting/gas-station/configure-sponsorship) | API reference for sponsorship configuration |