> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lightdash.com/llms.txt
> Use this file to discover all available pages before exploring further.

# External sources

> Upload a CSV or connect a Google Sheet, then query it next to your warehouse data

<Info>
  <Badge icon="test-pipe-2" color="orange" size="sm" shape="pill">Experimental</Badge> External sources are available to design partners behind the `external-sources` feature flag, and the flow, limits and wording on this page may change between releases. Contact [Lightdash support](mailto:support@lightdash.com) to enable it for your organization. Self-hosted instances also need an Enterprise license and the [setup below](#self-hosted-setup). [What Experimental means](/support/feature-maturity-levels).
</Info>

An external source brings data that lives outside your warehouse into a project: an uploaded CSV, or a tab of a Google Sheet. Lightdash reads it once, stores a typed copy, and turns it into a table you can explore, chart, put on dashboards and join to your warehouse data. Nothing changes in your dbt project.

Use it for small, hand-maintained data that never made it into the warehouse, such as monthly targets, a mapping of regions to owners, or a list of accounts to watch.

<Frame caption="A Google Sheet of monthly targets, explored like any other table">
  <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/06-sheet-explore.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=9857614ec48673bb06b127d46ecac6b7" alt="The Channel targets table from a Google Sheet, with Target month and Sum of Revenue target (USD) selected and the results by month" width="2880" height="1800" data-path="images/explore/external-sources/06-sheet-explore.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/06-sheet-explore-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=b38723326fc2c8c605d2d19c701ec51a" alt="The Channel targets table from a Google Sheet, with Target month and Sum of Revenue target (USD) selected and the results by month" width="2880" height="1800" data-path="images/explore/external-sources/06-sheet-explore-dark.png" />
</Frame>

## Before you start

* **Editor role or above.** Editors, developers and admins can add, refresh, rename and delete external sources. Everyone else in the project sees the tables, and the charts built on them follow normal [space permissions](/explore/spaces).
* **A header row.** The first row names the columns. Every following row is data.
* **For Google Sheets, access to the sheet.** The first time you connect a sheet, Lightdash asks your Google account for access to Google Sheets and to the Drive files you pick.
* **Size limits.** Up to 100 MB per file, 1,000,000 rows per table and 5 GB per organization.

<Warning>
  Everyone in the project can see an imported table, whatever the Google Sheet's own sharing settings. Lightdash reads the sheet with the Google access of the person who connected it and stores a copy. User attributes and row-level filters don't apply to external sources, so only import data that every project member may see.
</Warning>

## Upload a CSV

<Steps>
  <Step title="Open Add data">
    In the Tables sidebar, select **Add data**.

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/01-add-data-button.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=b1eb1a9bb2dfbe71d358293f1dadc6c0" alt="The Tables sidebar with the Add data button next to its heading" width="1120" height="660" data-path="images/explore/external-sources/01-add-data-button.png" />

      <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/01-add-data-button-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=f88a44d71b9f50999779e1d7ea5c37c4" alt="The Tables sidebar with the Add data button next to its heading" width="1120" height="660" data-path="images/explore/external-sources/01-add-data-button-dark.png" />
    </Frame>
  </Step>

  <Step title="Drop your file">
    Drop a CSV on the upload area, or click it to pick a file.

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/02-upload-csv.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=38d89a60d49af476b7e59636b1081a4d" alt="The Upload a CSV dialog with a drop area and a link to connect a Google Sheet instead" width="1240" height="520" data-path="images/explore/external-sources/02-upload-csv.png" />

      <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/02-upload-csv-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=955f3ba787b568bb1f6002cb43d2b138" alt="The Upload a CSV dialog with a drop area and a link to connect a Google Sheet instead" width="1240" height="520" data-path="images/explore/external-sources/02-upload-csv-dark.png" />
    </Frame>
  </Step>

  <Step title="Name the table and its columns">
    Give the table a name and check the type detected for each column. Rename any column whose name reads oddly, then select **Create table**. Lightdash opens the new table as soon as it's ready.

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/03-csv-preview.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=62a6e5ed715ae3c85dfd42d070954ed4" alt="The CSV preview with the table name sales_targets and editable names for each column, with the month column renamed to Target" width="1240" height="880" data-path="images/explore/external-sources/03-csv-preview.png" />

      <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/03-csv-preview-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=a3c25f866d6514642ed9ef351ea99a1b" alt="The CSV preview with the table name sales_targets and editable names for each column, with the month column renamed to Target" width="1240" height="880" data-path="images/explore/external-sources/03-csv-preview-dark.png" />
    </Frame>
  </Step>
</Steps>

## Connect a Google Sheet

<Steps>
  <Step title="Paste the sheet link">
    Select **Add data**, then **Connect a Google Sheet instead**. Paste the sheet's URL from your browser and name the table.

    Lightdash reads the tab the link points to. Open the tab you want before copying the URL, so the link ends in `#gid=…`. A link without a tab reads the first tab.

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/04-connect-sheet.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=cfe62873fa312f0f3a732a233039402e" alt="The Connect a Google Sheet dialog with a sheet URL and the table name channel_targets" width="1240" height="692" data-path="images/explore/external-sources/04-connect-sheet.png" />

      <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/04-connect-sheet-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=dff3e364d7388fe2e1a3bbbd593731e0" alt="The Connect a Google Sheet dialog with a sheet URL and the table name channel_targets" width="1240" height="692" data-path="images/explore/external-sources/04-connect-sheet-dark.png" />
    </Frame>
  </Step>

  <Step title="Connect your Google account">
    Select **Connect sheet**. If you haven't connected Google before, select **Connect Google account**, approve access in the pop-up, then select **Connect sheet** again.
  </Step>

  <Step title="Review the table">
    Once the import finishes, rename the table or any column, then select **Open table**.

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/05-review-table.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=c9626ba096c4b5e3abeebdb3555908e1" alt="The Review your table step listing seven imported columns with editable names, types and an Open table button" width="1240" height="1080" data-path="images/explore/external-sources/05-review-table.png" />

      <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/05-review-table-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=9d812c0b081abbfeb684ae7cc299769c" alt="The Review your table step listing seven imported columns with editable names, types and an Open table button" width="1240" height="1080" data-path="images/explore/external-sources/05-review-table-dark.png" />
    </Frame>
  </Step>
</Steps>

## What the table contains

Each column becomes a dimension with a detected type: string, number, date, timestamp or boolean. Date columns also get day, week, month, quarter and year breakdowns. Lightdash adds a **Total rows** metric, plus a sum and an average for every number column.

Column names are tidied into SQL-safe names, so `Região` becomes `regiao` and a column called `month` becomes `_month`. The name you see in the sidebar is the one you gave it while importing, or a readable version of the SQL name.

## Join with warehouse data

Select **Join with your warehouse data** under the table name to combine it with an explore from your dbt project, such as targets next to actual orders by month. Lightdash suggests a join on a matching field. The result is a [merge query](/explore/merge-queries), which you can save, add to dashboards and schedule like any other chart.

<Frame caption="Monthly targets from a Google Sheet joined to warehouse orders by month">
  <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/09-join-warehouse.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=228b355491c89b66f0ffcff76e96ff9c" alt="A merge query joining Channel targets Target month to Orders Order date month, with revenue targets next to total order amounts" width="2880" height="1800" data-path="images/explore/external-sources/09-join-warehouse.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/09-join-warehouse-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=d0e78f1d48bbc8961afa77cd76a9cb57" alt="A merge query joining Channel targets Target month to Orders Order date month, with revenue targets next to total order amounts" width="2880" height="1800" data-path="images/explore/external-sources/09-join-warehouse-dark.png" />
</Frame>

The join belongs to the chart, so each chart that needs targets next to actuals sets it up again.

## Keep the table up to date

An external source is a copy taken when you import it, and edits to the sheet or file don't show up until you refresh it. The menu next to the table name holds the source actions:

* **Refresh from Google Sheets** reads the sheet again. Column names you set are kept.
* **Replace file** uploads a new version of a CSV.
* **Reconnect Google account** makes your Google access the one used for future refreshes, for example when the person who connected the sheet leaves.
* **Rename table** changes the table and column names. Saved charts keep working.
* **View source details** previews the columns and the first rows.
* **Delete** removes the table. Charts built on it stop working.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/07-source-menu.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=1d5b1dc21a78331cc30d35170b2d9e5d" alt="The source menu next to the Channel targets table name, listing Merge another query, Refresh from Google Sheets, Reconnect Google account, Rename table, View source details and Delete" width="1520" height="940" data-path="images/explore/external-sources/07-source-menu.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/07-source-menu-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=1e4b72fc3526441ca983b1e5e80ff1dd" alt="The source menu next to the Channel targets table name, listing Merge another query, Refresh from Google Sheets, Reconnect Google account, Rename table, View source details and Delete" width="1520" height="940" data-path="images/explore/external-sources/07-source-menu-dark.png" />
</Frame>

<Frame caption="Renaming a column from Rename table">
  <img className="block dark:hidden" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/08-rename-table.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=160c441e41217815ed367575646e19fb" alt="The Rename table dialog with the table name and an editable name for every column, with channel renamed to Sales channel" width="1240" height="1076" data-path="images/explore/external-sources/08-rename-table.png" />

  <img className="hidden dark:block" src="https://mintcdn.com/lightdash/62Z0MJZvjjE2f5RM/images/explore/external-sources/08-rename-table-dark.png?fit=max&auto=format&n=62Z0MJZvjjE2f5RM&q=85&s=23ec64ad478e813220ca4b769f7d3d71" alt="The Rename table dialog with the table name and an editable name for every column, with channel renamed to Sales channel" width="1240" height="1076" data-path="images/explore/external-sources/08-rename-table-dark.png" />
</Frame>

## Self-hosted setup

External sources run on the same DuckDB engine and object storage as pre-aggregates, but they don't need pre-aggregate workers or NATS. You need:

* **An Enterprise license.** Set `LIGHTDASH_LICENSE_KEY`. See [enterprise features](/self-host/enterprise-features).
* **A bucket for the imported data.** Set the `PRE_AGGREGATE_RESULTS_S3_*` variables listed under [pre-aggregates](/self-host/customize-deployment/environment-variables#pre-aggregates). Lightdash stores each table under `external-sources/` in that bucket.
* **The feature flag.** Add `external-sources` to `LIGHTDASH_ENABLE_FEATURE_FLAGS`. See [feature flags](/self-host/customize-deployment/environment-variables#feature-flags).
* **For Google Sheets, a Google OAuth client.** Follow [configure a Google Sheets integration](/self-host/customize-deployment/configure-google-sheets-integration). Enable the Google Sheets API and the Google Drive API on the same Google Cloud project, and add `<SITE_URL>/api/v1/oauth/redirect/google` to the client's authorized redirect URIs.

To change the size limits, set `EXTERNAL_SOURCES_MAX_FILE_SIZE_BYTES`, `EXTERNAL_SOURCES_MAX_ROWS` or `EXTERNAL_SOURCES_MAX_ORGANIZATION_BYTES`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.