> For the complete documentation index, see [llms.txt](https://docs.ohalee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ohalee.com/products/networkeconomy/configuration.md).

# Configuration

```yaml
# =====================================================================
#  NetworkEconomy configuration
#  Cross-server, Vault-compatible economy for Paper/Spigot networks.
# =====================================================================

# A unique identifier for THIS server inside the network.
# It is used as the "source server" for transaction logs and to ignore
# Redis messages published by this same node. Must be different on every
# server of the network.
server-id: "lobby-1"

# ---------------------------------------------------------------------
# Storage: authoritative persistent store (MySQL / MariaDB).
# This is the single source of truth. All balances live here.
# ---------------------------------------------------------------------
storage:
  host: "127.0.0.1"
  port: 3306
  database: "networkeconomy"
  username: "root"
  password: "changeme"
  pool:
    # HikariCP pool sizing. Keep it small; economy queries are short.
    maximum-pool-size: 10
    minimum-idle: 2
  # Prefix for all tables created by the plugin (see schema.sql).
  table-prefix: "ne_"

# ---------------------------------------------------------------------
# Redis: pub/sub used to keep local caches coherent in real time.
# Optional but STRONGLY recommended for multi-server setups.
# ---------------------------------------------------------------------
redis:
  enabled: true
  host: "127.0.0.1"
  port: 6379
  username: ""      # leave empty unless your Redis uses ACL users
  password: ""      # leave empty for no auth
  database: 0
  # Channel used for balance-change broadcasts across the network.
  channel: "networkeconomy:updates"
  pool:
    minimum-size: 2
    maximum-size: 8

# ---------------------------------------------------------------------
# Local in-memory cache for online players.
# ---------------------------------------------------------------------
cache:
  expire-after-seconds: 300
  fallback-refresh-seconds: 30

# ---------------------------------------------------------------------
# Currencies. The first entry is the DEFAULT currency and the one exposed
# through the Vault Economy API.
# ---------------------------------------------------------------------
currencies:
  coins:
    display-name: "Coin"
    display-name-plural: "Coins"
    symbol: "$"
    symbol-before: true
    decimals: 2
    starting-balance: 100.0
    payable: true
    default: true
  gems:
    display-name: "Gem"
    display-name-plural: "Gems"
    symbol: "♦"
    symbol-before: false
    decimals: 0
    starting-balance: 0.0
    payable: false
    default: false

# ---------------------------------------------------------------------
# Command behaviour.
# ---------------------------------------------------------------------
commands:
  pay:
    minimum-amount: 0.01
    deny-self: true
    tax-percent: 0.0
  baltop:
    entries-per-page: 10
    cache-seconds: 60

# ---------------------------------------------------------------------
# Transaction history GUI.
# ---------------------------------------------------------------------
gui:
  history:
    title: "&8Transaction History"
    rows: 6
    entries-per-page: 45

# ---------------------------------------------------------------------
# Messages. Supports legacy '&' colour codes and MiniMessage tags.
# ---------------------------------------------------------------------
messages:
  prefix: "&6&lNE &8» &r"
  no-permission: "&cYou do not have permission to do that."
  player-only: "&cThis command can only be used by players."
  player-not-found: "&cPlayer &e{player}&c has never joined the network."
  invalid-amount: "&cPlease provide a valid, positive amount."
  invalid-currency: "&cUnknown currency: &e{currency}&c."
  balance-self: "&7Your balance: &a{balance}"
  balance-other: "&7{player}'s balance: &a{balance}"
  pay-sent: "&aYou sent &e{amount}&a to &e{receiver}&a."
  pay-received: "&aYou received &e{amount}&a from &e{sender}&a."
  pay-insufficient: "&cYou do not have enough {currency}."
  pay-self: "&cYou cannot pay yourself."
  eco-give: "&aGave &e{amount}&a to &e{player}&a. New balance: &e{balance}"
  eco-take: "&aTook &e{amount}&a from &e{player}&a. New balance: &e{balance}"
  eco-set: "&aSet &e{player}&a's balance to &e{balance}&a."
  eco-reset: "&aReset &e{player}&a's balance to the starting amount."
  error-generic: "&cAn internal error occurred. Please contact staff."

# Enable verbose logging for debugging (SQL / Redis traffic).
debug: false
```

## General

<table><thead><tr><th width="230">Key</th><th>Description</th></tr></thead><tbody><tr><td>server-id</td><td>Unique identifier for this server. Written to every transaction row as the origin server, and used to ignore this node's own Redis broadcasts. <strong>Must differ on every server</strong></td></tr><tr><td>debug</td><td>Verbose logging of SQL and Redis traffic</td></tr></tbody></table>

## storage

<table><thead><tr><th width="230">Key</th><th>Description</th></tr></thead><tbody><tr><td>host / port</td><td>MySQL / MariaDB address</td></tr><tr><td>database</td><td>Database name — must already exist</td></tr><tr><td>username / password</td><td>Credentials; the user needs table-creation rights on first start</td></tr><tr><td>pool.maximum-pool-size</td><td>Maximum HikariCP connections. Also determines the plugin's worker-thread count (minimum 2). Keep it small</td></tr><tr><td>pool.minimum-idle</td><td>Connections kept open while idle</td></tr><tr><td>table-prefix</td><td>Prefix applied to all three tables. Substituted for <code>{prefix}</code> in the schema</td></tr></tbody></table>

{% hint style="danger" %}
Changing `table-prefix` after first start points the plugin at a **new, empty set of tables** — the old balances are still in the database but no longer read. Only change it before going live.
{% endhint %}

## redis

<table><thead><tr><th width="230">Key</th><th>Description</th></tr></thead><tbody><tr><td>enabled</td><td>Turn real-time sync on or off. When off, caches refresh on a timer instead</td></tr><tr><td>host / port</td><td>Redis address</td></tr><tr><td>username</td><td>Only needed for Redis ACL users; leave empty otherwise</td></tr><tr><td>password</td><td>Leave empty for a Redis with no auth</td></tr><tr><td>database</td><td>Redis logical database index</td></tr><tr><td>channel</td><td>Pub/sub channel for balance broadcasts. <strong>Must be identical on every server</strong></td></tr><tr><td>pool.minimum-size / maximum-size</td><td>Lettuce connection-pool sizing. A dedicated connection is used for the subscription</td></tr></tbody></table>

## cache

<table><thead><tr><th width="230">Key</th><th>Description</th></tr></thead><tbody><tr><td>expire-after-seconds</td><td>How long a cached balance is trusted before a background refresh is forced. Only matters when Redis is off or a message was missed — with Redis on, this can stay high</td></tr><tr><td>fallback-refresh-seconds</td><td>With Redis disabled, how often online players are re-synced from the database. Ignored when Redis is enabled</td></tr></tbody></table>

{% hint style="info" %}
The cache only ever affects how fresh a *displayed* number is. Transactions are always evaluated by the database, so a stale cache can never cause a wrong deposit, withdrawal or transfer.
{% endhint %}

## currencies

Covered in detail on [currencies.md](/products/networkeconomy/currencies.md).

## commands

<table><thead><tr><th width="230">Key</th><th>Description</th></tr></thead><tbody><tr><td>pay.minimum-amount</td><td>Smallest amount accepted by <code>/pay</code></td></tr><tr><td>pay.deny-self</td><td>Block players from paying themselves</td></tr><tr><td>pay.tax-percent</td><td>Percentage removed from the transferred amount. <code>0.0</code> disables the tax</td></tr><tr><td>baltop.entries-per-page</td><td>Rows shown per <code>/baltop</code> page</td></tr><tr><td>baltop.cache-seconds</td><td>How long a computed <code>/baltop</code> page is reused before being queried again</td></tr></tbody></table>

{% hint style="warning" %}
With `pay.tax-percent` above zero, `/pay` cannot use a single atomic transfer: the sender is debited the full amount and the receiver credited the net, and the difference leaves circulation. Leave the tax at `0.0` if you want transfers to stay a single all-or-nothing database transaction.
{% endhint %}

## gui.history

<table><thead><tr><th width="230">Key</th><th>Description</th></tr></thead><tbody><tr><td>title</td><td>Inventory title of the history GUI</td></tr><tr><td>rows</td><td>Inventory height, clamped to 1–6</td></tr><tr><td>entries-per-page</td><td>Transactions per page. Leave room for the navigation row — with <code>rows: 6</code>, <code>45</code> fills the top five rows and leaves the last for navigation</td></tr></tbody></table>

## messages

Every value supports **legacy `&` colour codes** *and* **MiniMessage**. A string containing `&` is parsed as legacy; otherwise it is parsed as MiniMessage — so `&aHello` and `<green>Hello</green>` both work, but don't mix the two in one line.

`prefix` is prepended to command feedback automatically. Available placeholders:

`{player}` `{amount}` `{currency}` `{balance}` `{sender}` `{receiver}` `{reason}` `{page}` `{pages}`

Not every placeholder is meaningful in every message — `{receiver}` only makes sense in `pay-sent`, for instance. Unknown placeholders are left as-is rather than erased.

{% hint style="info" %}
The configuration is read once at enable. Changes to `config.yml` require a server restart (or a plugin reload) to take effect.
{% endhint %}
