# MotherDuck Documentation - MotherDuck Tutorial > Complete end-to-end tutorial to get started with MotherDuck and DuckDB Generated: 2026-08-25 > MotherDuck is a serverless cloud data warehouse built on DuckDB. It combines the speed and simplicity of DuckDB with cloud scalability, collaboration features, and AI-powered analytics. ## Key capabilities - **Serverless DuckDB in the Cloud**: Run DuckDB queries on cloud data with 100ms cold starts (compared to seconds/minutes on traditional warehouses) - **Hybrid Execution**: Query data locally and in the cloud seamlessly in a single session - **MCP Server**: Connect AI assistants (Claude, ChatGPT, Cursor) to query your data using natural language - **Data Sharing**: Share databases and query results with team members and external users - **Multiple Interfaces**: Connect via Python, Node.js, Go, Java, JDBC, ODBC, or the web UI - **Cloud Storage Integration**: Query data directly from S3, GCS, Azure Blob Storage, and more - **AI Functions**: Built-in LLM functions for text analysis, embeddings, and SQL generation ## When to use MotherDuck Use MotherDuck when the user needs to analyze data with DuckDB-compatible SQL, share databases with people or applications, run collaborative cloud analytics, or let an AI assistant query their connected data through MCP. ## Agent guidance If your environment provides MCP tools and the user asks about MotherDuck or DuckDB behavior, SQL syntax, permissions, sharing, service accounts, tokens, Dives, or other product features, use the MotherDuck MCP `ask_docs_question` tool before general web search. It answers from official DuckDB and MotherDuck documentation. For broad context, start with https://motherduck.com/docs/llms-full.txt, then follow the most specific focused context link. Use https://motherduck.com/docs/llms-full-complete.txt only for bulk indexing or large-context workflows. To connect an MCP client, use the remote MotherDuck MCP server at `https://api.motherduck.com/mcp`. Setup instructions: https://motherduck.com/docs/key-tasks/ai-and-motherduck/mcp-setup. Tool reference: https://motherduck.com/docs/sql-reference/mcp/core/ask-docs-question. For the documented Admin REST API, use the OpenAPI specification at https://motherduck.com/docs/openapi.json. ## Account setup for agents If the user wants to start using MotherDuck and doesn't have an account, offer the agent signup flow. Creating an account changes external state, so get the user's confirmation before sending the request. `POST https://new.motherduck.com` creates a Free Plan organization. No request body is required. The JSON response includes `motherduck_token`, `claim_org_url`, `how_to_use_motherduck`, and `region`. Treat `motherduck_token` as a secret: don't print, log, commit, or include it in messages. Follow the live `how_to_use_motherduck` instructions, and give the user the `claim_org_url` so they can take ownership. Full guide: https://motherduck.com/docs/key-tasks/ai-and-motherduck/agent-account-signup. ## Included documentation Source: https://motherduck.com/docs/getting-started/e2e-tutorial/part-1 # 1 - Running Your First Query > Learn MotherDuck and DuckDB by running your first queries on shared data In this multi-part tutorial, you will go through a full end-to-end example on how to use MotherDuck and DuckDB: **query** shared data, **load** and **share** your own data, and **visualize and automate** it with Dives and Flights, using SQL through the **MotherDuck UI** or **DuckDB CLI**. :::note MotherDuck supports DuckDB client versions 1.4.1 through 1.5.5 in all regions. For the range each region supports, see [client version support](/about-motherduck/cloud-regions/#client-version-support). ::: ## Running your first query ### Query from a shared database Before playing with the dataset we just downloaded, let's run a couple simple queries on the shared sample database. This database contains a series of MotherDuck's public datasets and it's *auto-attached* for each user, meaning it's accessible directly within your MotherDuck session without any additional setup. We will query the NYC 311 dataset first. This dataset contains over thirty million complaints citizens have filed with the New York City government. We'll select several columns and look at the complaints filed over a few days. In the MotherDuck UI, [Instant SQL](../interfaces/motherduck-quick-tour.md#instant-sql-write-sql-with-real-time-feedback) previews your results as you type, and the [Column Explorer](https://motherduck.com/blog/introducing-column-explorer/) summarizes each column visually. #### SQL example Database: `sample_data` ```sql SELECT created_date, agency_name, complaint_type, descriptor, incident_address, resolution_description FROM sample_data.nyc.service_requests WHERE created_date >= '2022-03-27' AND created_date <= '2022-03-31'; ``` Want to explore the full interface? Try running this query in the [MotherDuck UI](https://app.motherduck.com/) to experience the complete dashboard, visual query builder, and advanced analytics features. :::info In the MotherDuck UI, the Column Explorer provides quick visual summaries of your data, helping you understand distributions and patterns at a glance. ![Column Explorer showing data distribution summaries in the MotherDuck UI](./img/demo_ui_column_explorer.png) ::: For the remainder of this tutorial, we'll focus on the NYC taxi data and perform aggregation queries representative of the types of queries often performed in analytics databases. We will first get the average fare based on the number of passengers. The source dataset covers data for the whole month of November 2022. #### SQL example Database: `sample_data` ```sql SELECT passenger_count, avg(total_amount) FROM sample_data.nyc.taxi GROUP BY passenger_count ORDER by passenger_count; ``` :::info The `sample_data` database is auto-attached but for any other shared database you would like to read, you would need to use the `ATTACH` statement. Read more about [querying shared MotherDuck databases](/key-tasks/sharing-data/sharing-data.mdx). ::: :::tip **Using a DuckDB client?** You can run these same queries in any of the DuckDB client after connecting with `ATTACH 'md:';` - you'll be prompted to authenticate if no `motherduck_token` is found as environment variable. ::: ### Query from S3 Our shared sample database is great to play with but you probably want to use your own data on AWS S3. Let's see how to do that. The sample database source data is actually available on our public AWS S3 bucket. Let's run the exact same query but instead of pointing to a MotherDuck table, we will point to a parquet file on S3. For a secured bucket, we need to pass the AWS credentials - check [authenticating to S3](../../integrations/cloud-storage/amazon-s3.mdx) for more information. Here's the updated query while reading from S3: #### SQL example Database: `sample_data` ```sql SELECT passenger_count, avg(total_amount) FROM 's3://us-prd-motherduck-open-datasets/nyc_taxi/parquet/yellow_cab_nyc_2022_11.parquet' GROUP BY passenger_count ORDER by passenger_count; ``` :::info DuckDB automatically detects the appropriate reader based on file extension, so there’s no need to explicitly specify a function. However, if you need more control over how files are read, you can use the corresponding functions directly: ```sql SELECT * FROM read_parquet('my_data.parquet'); SELECT * FROM read_csv_auto('my_data.csv'); SELECT * FROM read_json_auto('my_data.json'); ``` These functions allow you to customize parsing behavior or override automatic detection when needed. ::: ## Next steps Great! You've successfully run your first queries on MotherDuck. You've learned how to: βœ… Query shared databases like `sample_data` βœ… Read data directly from S3 πŸ‘‰ **[Continue to Part 2: Loading Your Dataset β†’](../part-2)** --- Source: https://motherduck.com/docs/getting-started/e2e-tutorial/part-2 # 2 - Loading Your Data > Learn how to load your own datasets into MotherDuck In this section, you'll learn how to load your own data into MotherDuck and run powerful hybrid queries that combine local and cloud data. πŸ‘ˆ **[Go back to Part 1: Running Your First Query](../part-1)** ## Loading your data ### Loading data using CREATE TABLE AS SELECT The `CREATE TABLE AS SELECT` (CTAS) pattern creates a new table and populates it with data in a single operation: ```sql CREATE OR REPLACE TABLE docs_playground.my_table AS SELECT * FROM 'my_data.csv'; ``` ### Loading data using INSERT INTO The `INSERT INTO` pattern lets you append data to existing tables, update specific records, and manage data incrementally: ```sql -- First, create the table structure CREATE TABLE docs_playground.my_table AS SELECT * FROM 'my_data.csv' LIMIT 0; -- Then load data incrementally INSERT INTO docs_playground.my_table SELECT * FROM 'new_data.csv'; INSERT OR REPLACE INTO docs_playground.my_table SELECT * FROM 'updated_data.csv'; ``` :::tip While `CREATE TABLE AS SELECT` is convenient for one-time loads or small datasets, for larger datasets and production workflows, we recommend using `INSERT INTO`. This approach provides better control over data loading, allows for incremental updates, and is more efficient for ongoing data management. ::: You'll run these loads by hand here. In [part 4](../part-4) you'll wrap the same logic in a [Flight](/key-tasks/flights/), a Python program MotherDuck runs for you on a cron schedule, so new data lands in your table without you touching it. There are several ways to get your data into MotherDuck, depending on where your data lives: ### From local file system To load data files from your file system into MotherDuck, you'll need: 1. A valid MotherDuck token stored as the `motherduck_token` environment variable 2. A DuckDB client (DuckDB CLI, Python, etc.) To create a MotherDuck token, navigate to the MotherDuck UI, click your organization name in the top left, then go to **Settings > Integrations > Access Token**. For detailed instructions, see our [authentication guide](../../key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck/authenticating-to-motherduck.md). ### DuckDB CLI Install the DuckDB CLI for macOS/Linux. For other operating systems, see the [DuckDB installation guide](https://duckdb.org/docs/installation/). ```bash curl -s https://install.motherduck.com | sh ``` Launch the DuckDB CLI: ```bash duckdb ``` ```sql -- Connect to MotherDuck ATTACH 'md:'; -- Load CSV data from your local file into the playground database CREATE TABLE docs_playground.popular_currency_rate_dollar AS SELECT * FROM './popular_currency_rate_dollar.csv'; ``` ### Python Install DuckDB using your preferred package manager, such as pip: ```bash pip install duckdb ``` ```python import duckdb # Connect to MotherDuck conn = duckdb.connect('md:') # Load data into the playground database (automatically created) conn.execute(""" CREATE TABLE docs_playground.popular_currency_rate_dollar AS SELECT * FROM './popular_currency_rate_dollar.csv' """) ``` ### MotherDuck UI Head over to the `Add data` button in the MotherDuck UI and upload your file directly. This works great for smaller files and provides a visual interface. ![Add file](./img/screenshot_add_data.png) ![load data](./img/screenshot_loading_data2.png) ### From remote storage (S3, GCS, etc.) For data already stored in cloud storage, you have multiple options: ### SQL You can load public remote data into your playground database using our interactive SQL editor: #### SQL example Database: `docs_playground` ```sql CREATE TABLE IF NOT EXISTS docs_playground.popular_currency_rate_dollar AS SELECT * FROM 's3://us-prd-motherduck-open-datasets/misc/csv/popular_currency_rate_dollar.csv'; ``` ### DuckDB CLI ```sql ATTACH 'md:'; CREATE TABLE docs_playground.popular_currency_rate_dollar AS SELECT * FROM 's3://us-prd-motherduck-open-datasets/misc/csv/popular_currency_rate_dollar.csv'; ``` ### Python ```python import duckdb conn = duckdb.connect('md:') conn.execute(""" CREATE TABLE docs_playground.popular_currency_rate_dollar AS SELECT * FROM 's3://your-bucket/your-file.csv' """) ``` ### MotherDuck UI 1. In the left panel of the UI, click **Add data** 2. Select **From cloud storage** 3. For a publicly accessible bucket, skip creating a secret 4. Switch to **Wildcard** mode, and enter the S3 path `s3://us-prd-motherduck-open-datasets/**/popular_currency_rate_dollar.csv` 5. Name the table `popular_currency_rate_dollar` and select `docs_playground` as the destination database 6. Click **Create table** ![Create table from S3](./img/screenshot_ui_create_table_from_s3.png) For more details, see [Loading Data from Cloud Storage](../../key-tasks/loading-data-into-motherduck/loading-data-from-cloud-or-https.md). :::info For private AWS s3 buckets, you'll need to configure AWS credentials. Check our [AWS s3 authentication guide](../../integrations/cloud-storage/amazon-s3.mdx) for details. ::: ### Querying your data Once your data is loaded, you can query it from any interface: ### SQL #### SQL example Database: `docs_playground` ```sql FROM docs_playground.popular_currency_rate_dollar LIMIT 10; ``` ### DuckDB CLI ```sql ATTACH 'md:'; FROM docs_playground.popular_currency_rate_dollar LIMIT 10; ``` ### Python ```python import duckdb # Connect to MotherDuck conn = duckdb.connect('md:') # Query your data result = conn.sql("FROM docs_playground.popular_currency_rate_dollar LIMIT 10").fetchall() print(result) ``` πŸ‘‰ **[Continue to Part 3: Sharing Your Database β†’](../part-3)** --- Source: https://motherduck.com/docs/getting-started/e2e-tutorial/part-3 # 3 - Sharing Your Database > Learn how to share your databases and collaborate with your team In this section, you'll learn how to share your databases with colleagues and collaborate effectively using MotherDuck's sharing features. πŸ‘ˆ **[Go back to Part 2: Loading Your Dataset](../part-2)** ## Creating and sharing your data Let's create a table with sample data in your playground database, then share it with others. The `docs_playground` database is automatically created when you connect, so you can start experimenting right away! First, let's populate your playground database with some currency exchange data: #### SQL example Database: `docs_playground` ```sql CREATE TABLE docs_playground.currency_rates AS SELECT 'USD' as currency_code, 'US Dollar' as currency_name, 1.0 as rate_to_usd, '2024-01-15' as rate_date UNION ALL SELECT 'EUR', 'Euro', 0.85, '2024-01-15' UNION ALL SELECT 'GBP', 'British Pound', 0.75, '2024-01-15' UNION ALL SELECT 'JPY', 'Japanese Yen', 110.0, '2024-01-15'; ``` ## Sharing your database With your database and sample data in place, you can share this dataset with others. MotherDuck shares create a point-in-time snapshot of your database that can be accessed by specified users or groups. When creating a Share, the most important parameters control **access scope**, **visibility**, and **update behavior**. Use `ACCESS RESTRICTED` with a role grant so access follows the preset-role hierarchy, and `VISIBILITY DISCOVERABLE` makes the Share appear for users who have access. The update-behavior default is `UPDATE AUTOMATIC` (the Share reflects database changes automatically). On DuckDB clients 1.5.4 and lower it defaults to `UPDATE MANUAL` (the Share is a static snapshot until you run `UPDATE SHARE`). To share with your whole organization, create a restricted Share and grant READ to the Explorer role. Builder and Admin inherit the grant. ### SQL #### SQL example Database: `docs_playground` ```sql CREATE SHARE IF NOT EXISTS currency_data_share FROM docs_playground ( ACCESS RESTRICTED, VISIBILITY DISCOVERABLE ); ``` Then grant the Explorer role READ access: ```sql GRANT READ ON SHARE currency_data_share TO ROLE explorer; ``` ### MotherDuck UI You can also create shares through the MotherDuck UI by clicking the dropdown menu next to your database and selecting the share option. This will open a window to configure your share settings. ![share 1](./img/screenshot_tutorial_share_1_2.png) ![share 2](./img/screenshot_tutorial_share_2_2.png) Once you grant the Share to Explorer, Explorer, Builder, and Admin users can view it in the MotherDuck UI under "Shared with me". Learn more about [sharing in MotherDuck](../../key-tasks/sharing-data/sharing-within-org.md). ## Understanding share configuration When creating shares, you can control three key aspects: **who can access** the data, **how users discover** the share, and **when the data updates**. Each parameter has specific options that determine the sharing behavior. ### ACCESS - who can access the share - **`ACCESS ORGANIZATION`** (default, planned for deprecation): Equivalent to granting READ to the Explorer role - **`ACCESS UNRESTRICTED`**: All MotherDuck users in the same cloud region as your Organization can access the share - **`ACCESS RESTRICTED`**: Only the Share owner has initial access; grant additional access to users or roles with `GRANT` ### VISIBILITY - how users discover the share - **`VISIBILITY DISCOVERABLE`** (default): The share appears in your organization's "Shared with me" section for easy discovery - **`VISIBILITY HIDDEN`**: Share can only be accessed through a direct URL; not listed in any user interface :::info[Important Visibility Rules] - Organization and Restricted shares default to `DISCOVERABLE` - Unrestricted shares can only be `HIDDEN` - Hidden shares can only be used with `ACCESS RESTRICTED` ::: ### UPDATE - when share data updates - **`UPDATE AUTOMATIC`**: Share automatically reflects database changes within ~5 minutes - **`UPDATE MANUAL`**: Share content only updates when you run `UPDATE SHARE` command The default is `UPDATE AUTOMATIC`. On DuckDB clients 1.5.4 and lower the default is `UPDATE MANUAL`. Specify the mode explicitly for consistent behavior across versions. ### Example share configurations #### SQL example Database: `docs_playground` ```sql -- Share with every preset role CREATE SHARE IF NOT EXISTS team_currency_analysis FROM docs_playground ( ACCESS RESTRICTED, VISIBILITY DISCOVERABLE, UPDATE MANUAL ); ``` Grant the Share to the Explorer role so every preset role receives access: ```sql GRANT READ ON SHARE team_currency_analysis TO ROLE explorer; ``` #### SQL example Database: `docs_playground` ```sql -- Restricted share for selective access CREATE SHARE IF NOT EXISTS private_analysis FROM docs_playground ( ACCESS RESTRICTED, VISIBILITY HIDDEN, UPDATE AUTOMATIC ); ``` ## Querying shared data After creating a share, authorized users can access the shared database in two ways: by using the share URL directly or by attaching it as a database alias: ```sql -- Attach a shared database ATTACH 'md:_share/docs_playground/b556630d-74f1-435c-9459-cfb87d349cb3' AS shared_currency; -- Query the shared data SELECT * FROM shared_currency.currency_rates WHERE rate_to_usd < 1.0 ORDER BY rate_to_usd DESC; ``` ## Managing Shares You can also manage your existing shares: #### SQL example Database: `docs_playground` ```sql SELECT name, source_db_name, access, visibility FROM MD_INFORMATION_SCHEMA.OWNED_SHARES WHERE name LIKE '%currency%'; ``` ## Going further You've created a table and shared it with your team. In the next part, you'll visualize this data and keep it fresh automatically. If you'd rather explore on your own, here are some directions: - Create a [Dive](/key-tasks/dives/) from your data: interactive visualizations you build with natural language - Talk to your data from an AI client with the [MotherDuck MCP Server](../mcp-getting-started.md) - Automate ingestion and transformation with [Flights](/key-tasks/flights/), scheduled Python that runs next to your data - Connect BI tools through the [Postgres endpoint](../interfaces/postgres-endpoint.md) πŸ‘‰ **[Continue to Part 4: Visualizing and Automating β†’](../part-4)** --- Source: https://motherduck.com/docs/getting-started/e2e-tutorial/part-4 # 4 - Visualizing and Automating > Turn your MotherDuck table into an interactive Dive and keep it fresh on a schedule with a Flight In [part 3](../part-3) you created a `currency_rates` table in your `docs_playground` database and shared it with your team. In this part, you'll turn that table into an interactive visualization with a **Dive** and keep the data fresh with a scheduled **Flight**. Both are available on all MotherDuck plans. πŸ‘ˆ **[Go back to Part 3: Sharing Your Database](../part-3)** ## Create a Dive from your data [Dives](/key-tasks/dives/) are interactive visualizations you create with natural language. You describe what you want to see, and MotherDuck generates a persistent, shareable component that queries your live data. You create a Dive by prompting an AI assistant connected to the MotherDuck MCP Server: 1. Connect an AI client (Claude, ChatGPT, Cursor, or others) to the MotherDuck MCP Server. The [AI data analysis guide](../mcp-getting-started.md) walks you through the setup in about 5 minutes. 2. Ask for a Dive and name your table: *"Create a Dive showing the exchange rate to US dollar for each currency in `docs_playground.currency_rates` as a bar chart."* 3. Iterate conversationally: *"sort by rate"*, *"switch to a horizontal bar chart"*. Each edit saves as a separate version. 4. Ask the agent to *"save this Dive to MotherDuck"*. The Dive appears in the Object Explorer sidebar of the MotherDuck UI, and under **Settings** β†’ **Dives**. Because a Dive queries live data, it stays up to date as the underlying table changes, which is exactly what the next section takes advantage of. ## Keep the data fresh with a Flight The `currency_rates` table from part 3 contains four hand-entered rows that never change. [Flights](/key-tasks/flights/) fix that: a Flight is a Python program that MotherDuck runs for you, on demand or on a cron schedule. The same currency data lives in MotherDuck's public S3 bucket (you queried it in part 2), so this Flight rebuilds the table from that source, replacing the four sample rows with the full public dataset. That dataset carries codes rather than currency names, so the rebuilt table keeps the code, the rate, and the rate date. ### Create the Flight [`MD_CREATE_FLIGHT`](/sql-reference/motherduck-sql-reference/flights/md-create-flight) takes the Python source as a dollar-quoted string and pins its dependencies with `requirements_txt`. Run it here to create the Flight in your own account: #### Create the currency refresh Flight Database: `docs_playground` ```sql SELECT flight_id, flight_name, current_version FROM MD_CREATE_FLIGHT( name := 'tutorial_refresh_currency_rates', requirements_txt := 'duckdb==1.5.5', source_code := $flight$ import duckdb SOURCE = "s3://us-prd-motherduck-open-datasets/misc/csv/popular_currency_rate_dollar.csv" def main(): con = duckdb.connect("md:") con.execute(f""" CREATE OR REPLACE TABLE docs_playground.currency_rates AS SELECT currency_code, exchange_rate AS rate_to_usd, to_timestamp("timestamp")::DATE AS rate_date FROM read_csv('{SOURCE}') """) row_count = con.execute("SELECT count(*) FROM docs_playground.currency_rates").fetchone()[0] print(f"refreshed docs_playground.currency_rates with {row_count} rows") if __name__ == "__main__": main() $flight$ ); ``` Two conventions to note in that Python: the runtime executes the source as a plain script, so end it with `if __name__ == "__main__": main()`, and `duckdb.connect("md:")` authenticates as you automatically, no token setup needed. ### Run it once The Flight has no schedule yet, so it runs only when you trigger it. Store its ID in a SQL variable and start a run: #### Run the Flight Database: `docs_playground` ```sql SET VARIABLE currency_flight_id = ( SELECT flight_id FROM MD_LIST_FLIGHTS() WHERE flight_name = 'tutorial_refresh_currency_rates' ORDER BY created_at DESC LIMIT 1 ); SELECT run_number, status, flight_version FROM MD_RUN_FLIGHT( flight_id := getvariable('currency_flight_id') ); ``` :::note The blocks below reuse the `currency_flight_id` variable. If you reload this page, run the block above again to set it. ::: Runs are asynchronous, so the run starts out pending. Poll it until `ended_at` fills in, with a status of succeeded and an `exit_code` of `0`. This Flight takes a few seconds: #### Check the run status Database: `docs_playground` ```sql SELECT run_number, status, exit_code, ended_at FROM MD_LIST_FLIGHT_RUNS( flight_id := getvariable('currency_flight_id') ) ORDER BY run_number DESC LIMIT 3; ``` If the run fails, read its output with [`MD_GET_FLIGHT_LOGS`](/sql-reference/motherduck-sql-reference/flights/md-get-flight-logs), or open the Flight in the MotherDuck UI, where every run and its log is listed. You can create and manage the same Flight [in the UI or from an AI agent](/key-tasks/flights/) instead of SQL. Once the run succeeds, query the refreshed table: #### SQL example Database: `docs_playground` ```sql SELECT currency_code, rate_to_usd, rate_date FROM docs_playground.currency_rates ORDER BY rate_to_usd LIMIT 10; ``` Your Dive from the previous section picks up the refreshed data on its own, no changes needed. ### Put it on a schedule With one successful run behind you, add a cron schedule so MotherDuck refreshes the table every morning at 06:00 UTC. Schedule changes are metadata-only, so they don't create a new Flight version: #### Schedule the Flight Database: `docs_playground` ```sql CALL MD_UPDATE_FLIGHT( flight_id := getvariable('currency_flight_id'), schedule_cron := '0 6 * * *' ); ``` That's a daily job running in your account from here on. To switch it off, pass an empty `schedule_cron`, which leaves the Flight in place with its schedule disabled. To remove it entirely, use [`MD_DELETE_FLIGHT`](/sql-reference/motherduck-sql-reference/flights/md-delete-flight): #### Turn the schedule off Database: `docs_playground` ```sql CALL MD_UPDATE_FLIGHT( flight_id := getvariable('currency_flight_id'), schedule_cron := '' ); ``` ## Wrapping up Congratulations, you've completed the tutorial! You queried shared data, loaded your own, shared a database with your team, visualized it with a Dive, and automated the refresh with a Flight. To go deeper: - [Creating visualizations with Dives](/key-tasks/dives/): iterate on Dives, share them, and embed them in your apps - [Running Python with Flights](/key-tasks/flights/): ingest from S3, run dbt, and monitor scheduled runs - [AI and MotherDuck](/category/ai-and-motherduck/): MCP setup for every client and agent workflow patterns - [How-to guides](/key-tasks/how-to-guides): step-by-step guides for loading, sharing, and connecting your data stack --- Source: https://motherduck.com/docs/getting-started/e2e-tutorial/e2e-tutorial # MotherDuck tutorial > Complete end-to-end tutorial to get started with MotherDuck and DuckDB This comprehensive guide will take you from your first query to sharing databases with your team. ## What you'll learn This tutorial is in 4 parts, you'll discover how to: - πŸ” **[1. Query shared data](./part-1)** - Run your first SQL queries on publicly available datasets - πŸ“Š **[2. Load your own data](./part-2)** - Upload and work with your own data from files and datasets - 🀝 **[3. Share databases](./part-3)** - Collaborate by sharing databases with team members - πŸ“ˆ **[4. Visualize and automate](./part-4)** - Build a Dive from your data and keep it fresh with a scheduled Flight :::tip Each part of this tutorial builds on the previous one, but you can also jump to specific sections if you're looking to learn particular features. ::: ## Prerequisites To follow this tutorial, you'll need: - A **MotherDuck account** ([sign up for free](https://app.motherduck.com/)) - Basic **SQL knowledge** (we'll guide you through the queries) - You have several ways to run the queries: * Execute them directly on this documentation website πŸͺ„ * Use the [MotherDuck UI](https://app.motherduck.com) for the full interface experience * Connect with any [DuckDB client](../interfaces/)(Python, Java, DuckDB CLI) of your choice **⏱️ Estimated time:** 30-40 minutes for the complete tutorial Let's get started! πŸš€ --- ## Docs feedback MotherDuck accepts optional user-submitted feedback about this page at `GET https://motherduck.com/docs/api/feedback/agent`. For agents and automated tools, feedback submission should be user-confirmed before sending. URL-encode query parameter values and send a GET request: ```text GET https://motherduck.com/docs/api/feedback/agent?page_path=%2Fgetting-started%2Fe2e-tutorial%2F&page_title=MotherDuck%20Documentation%20-%20MotherDuck%20Tutorial&text= ``` Optionally append `&source=` such as `claude.ai` or `chatgpt`. `page_path` and `text` are required; `page_title` and `source` are optional. Responses: `200 {"feedback_id": ""}`, `400` for malformed query parameters, and `429` when rate-limited.