Malloy Documentation
search

Configure database connections for Malloy Publisher deployments. For an overview of supported databases, see Database Support.


Configuration File

Publisher uses publisher.config.json for database connections. This file lives in your server root directory.

Important: Publisher does not support environment variable substitution. Put actual credential values directly in the config file.

Basic Structure

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "connection_name",
          "type": "backend_type",
          "<type>Connection": {
            ...connection options...
          }
        }
      ],
      "packages": [
        {
          "name": "my-package",
          "location": "./my-package"
        }
      ]
    }
  ]
}

Each connection object requires:

  • name: The connection name used in your Malloy code

  • type: The backend type (duckdb, postgres, bigquery, etc.)

  • Type-specific options nested under <type>Connection (e.g., postgresConnection, bigqueryConnection)

Note: For packages with local parquet/CSV files, you don't need a connections config at all — Publisher automatically uses DuckDB.


DuckDB (Local Parquet Files)

For packages with embedded parquet/CSV files, no connection configuration is needed. Publisher automatically uses DuckDB for local data files:

{
  "projects": [
    {
      "name": "default",
      "packages": [
        {
          "name": "my-analytics",
          "location": "./my-analytics"
        }
      ]
    }
  ]
}

In your Malloy model, reference files relative to the package root:

source: flights is duckdb.table('data/flights.parquet')

Folder structure:

my-analytics/
├── publisher.json
├── model.malloy
└── data/
    └── flights.parquet

DuckDB with Attached Databases

DuckDB can federate queries to external databases (BigQuery, Snowflake, PostgreSQL) using attached databases. This lets you query cloud data warehouses through DuckDB.

Attach BigQuery:

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "duckdb",
          "type": "duckdb",
          "duckdbConnection": {
            "attachedDatabases": [
              {
                "name": "my_bq",
                "type": "bigquery",
                "bigqueryConnection": {
                  "defaultProjectId": "my-gcp-project",
                  "serviceAccountKeyJson": "{ \"type\": \"service_account\", ... }"
                }
              }
            ]
          }
        }
      ],
      "packages": [...]
    }
  ]
}

In your Malloy model:

source: events is duckdb.table('my_bq.my_dataset.events')

Attach Snowflake:

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "duckdb",
          "type": "duckdb",
          "duckdbConnection": {
            "attachedDatabases": [
              {
                "name": "my_sf",
                "type": "snowflake",
                "snowflakeConnection": {
                  "account": "myorg-myaccount",
                  "username": "my_user",
                  "password": "my_password",
                  "database": "analytics",
                  "warehouse": "compute_wh"
                }
              }
            ]
          }
        }
      ],
      "packages": [...]
    }
  ]
}

Attach PostgreSQL:

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "duckdb",
          "type": "duckdb",
          "duckdbConnection": {
            "attachedDatabases": [
              {
                "name": "my_pg",
                "type": "postgres",
                "postgresConnection": {
                  "host": "db.example.com",
                  "port": 5432,
                  "databaseName": "analytics",
                  "userName": "readonly_user",
                  "password": "my_password"
                }
              }
            ]
          }
        }
      ],
      "packages": [...]
    }
  ]
}

Multiple attached databases:

{
  "duckdbConnection": {
    "attachedDatabases": [
      {
        "name": "warehouse",
        "type": "bigquery",
        "bigqueryConnection": { ... }
      },
      {
        "name": "app_db",
        "type": "postgres",
        "postgresConnection": { ... }
      }
    ]
  }
}

MotherDuck

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "md",
          "type": "motherduck",
          "motherduckConnection": {
            "accessToken": "your_motherduck_token_here",
            "database": "my_database"
          }
        }
      ],
      "packages": [...]
    }
  ]
}

BigQuery

With service account (recommended for production):

Embed the service account JSON directly in the config:

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "bigquery",
          "type": "bigquery",
          "bigqueryConnection": {
            "defaultProjectId": "my-gcp-project",
            "location": "US",
            "serviceAccountKeyJson": "{\n  \"type\": \"service_account\",\n  \"project_id\": \"my-gcp-project\",\n  ...rest of service account JSON...\n}"
          }
        }
      ],
      "packages": [...]
    }
  ]
}

With gcloud auth (development only):

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "bigquery",
          "type": "bigquery",
          "bigqueryConnection": {
            "defaultProjectId": "my-gcp-project",
            "location": "US"
          }
        }
      ],
      "packages": [...]
    }
  ]
}

Snowflake

Password authentication:

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "snowflake",
          "type": "snowflake",
          "snowflakeConnection": {
            "account": "myorg-myaccount",
            "username": "publisher_user",
            "password": "your_password_here",
            "warehouse": "compute_wh",
            "database": "analytics",
            "schema": "public"
          }
        }
      ],
      "packages": [...]
    }
  ]
}

RSA private key authentication:

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "snowflake",
          "type": "snowflake",
          "snowflakeConnection": {
            "account": "myorg-myaccount",
            "username": "publisher_user",
            "privateKey": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBAD...your-key-here...\n-----END PRIVATE KEY-----",
            "privateKeyPass": "your_passphrase_if_encrypted",
            "warehouse": "compute_wh",
            "database": "analytics"
          }
        }
      ],
      "packages": [...]
    }
  ]
}

PostgreSQL

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "postgres",
          "type": "postgres",
          "postgresConnection": {
            "host": "db.example.com",
            "port": 5432,
            "databaseName": "analytics",
            "userName": "publisher_readonly",
            "password": "your_password_here"
          }
        }
      ],
      "packages": [...]
    }
  ]
}

MySQL

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "mysql",
          "type": "mysql",
          "mysqlConnection": {
            "host": "db.example.com",
            "port": 3306,
            "database": "analytics",
            "user": "publisher_readonly",
            "password": "your_password_here"
          }
        }
      ],
      "packages": [...]
    }
  ]
}

Trino and Presto

{
  "projects": [
    {
      "name": "default",
      "connections": [
        {
          "name": "trino",
          "type": "trino",
          "trinoConnection": {
            "server": "https://trino.example.com",
            "port": 8443
          }
        }
      ],
      "packages": [...]
    }
  ]
}

For Presto, use "type": "presto" with the same configuration options.


Multi-Environment Configuration

You can configure multiple projects for different environments:

{
  "projects": [
    {
      "name": "staging",
      "connections": [
        {
          "name": "postgres",
          "type": "postgres",
          "postgresConnection": {
            "host": "staging-db.example.com",
            "port": 5432,
            "databaseName": "analytics",
            "userName": "staging_user",
            "password": "staging_password"
          }
        }
      ],
      "packages": [
        {
          "name": "analytics",
          "location": "./packages/analytics"
        }
      ]
    },
    {
      "name": "production",
      "connections": [
        {
          "name": "postgres",
          "type": "postgres",
          "postgresConnection": {
            "host": "prod-db.example.com",
            "port": 5432,
            "databaseName": "analytics",
            "userName": "prod_readonly",
            "password": "prod_password"
          }
        }
      ],
      "packages": [
        {
          "name": "analytics",
          "location": "./packages/analytics"
        }
      ]
    }
  ]
}

Next Steps