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

# Choosing your deployment

> This guide will help you to identify the right Omni deployment pattern for your environment based on your infrastructure, team structure, and content governance requirements

export const categoryIcons = {
  'administration': 'lock',
  'api': 'terminal',
  'connections': 'database',
  'dashboards': 'table-columns',
  'embed': 'code',
  'errors': 'exclamation',
  'migration': 'angles-right',
  'modeling': 'wrench',
  'patterns': 'plus',
  'schedules & alerts': 'envelope',
  'visualizations': 'chart-column',
  'workbooks': 'book'
};

export const GuideSidebar = ({category, relatedLinks, updatedDate}) => {
  const [progress, setProgress] = React.useState(0);
  React.useEffect(() => {
    const sidebar = document.querySelector('.guide-sidebar');
    if (!sidebar) return;
    let container = sidebar.parentElement;
    while (container && !container.querySelector('.guide-header')) {
      container = container.parentElement;
    }
    if (container && !container.classList.contains('guide-page-layout')) {
      container.classList.add('guide-page-layout');
    }
  }, []);
  React.useEffect(() => {
    const handleScroll = () => {
      const scrollTop = window.scrollY;
      const docHeight = document.documentElement.scrollHeight - window.innerHeight;
      const scrollPercent = docHeight > 0 ? scrollTop / docHeight * 100 : 0;
      setProgress(Math.min(100, Math.max(0, scrollPercent)));
    };
    window.addEventListener('scroll', handleScroll, {
      passive: true
    });
    handleScroll();
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);
  const icon = category ? categoryIcons[category.toLowerCase()] || 'book' : 'book';
  return <aside className="guide-sidebar">
      <div className="guide-sidebar-content">
        <a href="/guides" className="guide-sidebar-back">
          <Icon icon="arrow-left" iconType="solid" size={14} />
          <span>All guides</span>
        </a>

        <div className="guide-sidebar-section">
          <div className="guide-sidebar-label">Progress</div>
          <div className="guide-sidebar-progress">
            <div className="guide-mascot">
              <svg viewBox="0 0 688 690" width="48" height="48">
                <defs>
                  <clipPath id="progressClip">
                    <rect x="0" y={0} width="688" height={progress * 6.9} />
                  </clipPath>
                </defs>

                {}
                <path d="M343.67 1.5C542.684 1.5 685.84 149.351 685.84 344.84C685.84 540.328 542.685 688.18 343.67 688.18C144.655 688.18 1.5 540.318 1.5 344.84C1.50007 149.361 144.655 1.50005 343.67 1.5Z" fill="#FCFCF7" stroke="#FF5FA2" strokeWidth="3" />

                {}
                <path d="M343.67 0C143.81 0 0 148.55 0 344.84C0 541.13 143.81 689.68 343.67 689.68C543.53 689.68 687.34 541.14 687.34 344.84C687.34 148.54 543.53 0 343.67 0Z" fill="#FF5FA2" clipPath="url(#progressClip)" />

                {}
                <path d="M337.89 319.29C337.89 336.75 322.49 350.14 302.81 349.83C286.18 349.57 273.89 337.29 274.37 321.45C274.88 304.82 290.91 290.88 309.98 290.44C325.69 290.09 337.88 302.69 337.88 319.29H337.89Z" fill="#4D122C" />
                <path d="M566.17 319.29C566.17 336.75 550.77 350.14 531.09 349.83C514.46 349.57 502.17 337.29 502.65 321.45C503.16 304.82 519.19 290.88 538.26 290.44C553.97 290.09 566.16 302.69 566.16 319.29H566.17Z" fill="#4D122C" />
                <path d="M367.74 342.07C360.22 346.32 359.4 354.9 370.62 366.4C381.85 377.9 399.76 389.56 420.81 389.18C441.88 389.1 460.67 377.72 472.47 363.53C473.83 361.93 478.84 356.88 478.51 351.07C478.32 348.35 476.17 341.19 467.83 341.38C463.46 341.44 461.21 343.68 456.69 347.36C445.2 356.14 432.7 361.21 420.56 361.27C408.43 361.43 395.68 356.17 385.39 347.22C380.32 342.81 375.25 337.82 367.74 342.07Z" fill="#4D122C" />
              </svg>
            </div>
            <span className="guide-sidebar-progress-text">{Math.round(progress)}%</span>
          </div>
        </div>

        {category && <div className="guide-sidebar-section">
            <div className="guide-sidebar-label">Category</div>
            <div className="guide-sidebar-category">
              <Icon icon={icon} iconType="solid" size={14} />
              <span>{category}</span>
            </div>
          </div>}

        {updatedDate && <div className="guide-sidebar-section">
            <div className="guide-sidebar-label">Last updated</div>
            <div className="guide-sidebar-date">{updatedDate}</div>
          </div>}

        {relatedLinks && relatedLinks.length > 0 && <div className="guide-sidebar-section">
            <div className="guide-sidebar-label">Related</div>
            <ul className="guide-sidebar-links">
              {relatedLinks.map((link, index) => <li key={index}>
                  <a href={link.href}>{link.title}</a>
                </li>)}
            </ul>
          </div>}
      </div>
    </aside>;
};

export const GuideTitle = ({title}) => {
  return <div className="guide-header">
      <h1 className="guide-title">{title}</h1>
    </div>;
};

<GuideSidebar categoryIcons={categoryIcons} category="deployment" updatedDate="July 2026" />

<GuideTitle title="Choosing your deployment" />

Omni offers a range of deployment options, from a single-instance setup to multi-instance, multi-region architectures. This guide helps you identify the right starting point based on your actual requirements.

**Our recommendation: Start with the simplest architecture that meets your requirements.** The vast majority of teams can accomplish what they need within a [single Omni instance](/guides/deployment/single-instance-git-dbt). Multi-instance deployments add operational overhead — they're worth it when the requirements genuinely call for them, and not before.

## What's your primary requirement?

<AccordionGroup>
  <Accordion title="I need to safely develop and test model changes before they affect production users">
    **→ [Single instance deployment with git and dbt](/guides/deployment/single-instance-git-dbt)**

    This is the most common Omni deployment. A single instance with git integration gives you branch-based development, pull request workflows, and the Content Validator — everything you need to manage changes safely without running a separate production environment.

    If you're using dbt, the same guide covers connecting your dbt project and syncing metadata into the model.
  </Accordion>

  <Accordion title="I need separate development/staging and production databases and need to validate changes against non-production data">
    **→ [Single instance deployment with dynamic database environments](/guides/deployment/single-instance-dynamic-connections)**

    Dynamic connection environments let your developers switch to a staging database within an Omni branch — so model changes can be tested against non-production data without maintaining a separate Omni instance.

    This is the right choice when:

    * You have `analytics_prod` and `analytics_dev` databases
    * All developers are allowed to see both databases
    * You don't need true environment isolation between developers and production users
  </Accordion>

  <Accordion title="I have strict separation requirements between development/staging and production environments within a single region">
    **→ [Multiple instance deployment with git follower](/guides/deployment/multi-instance-prod-stage)**

    When you need two fully isolated Omni environments — one where development happens and one where production users live — a two-instance git follower setup is the right architecture. Developers work entirely in staging; production is updated only through deliberate git-based promotions.

    This is the right choice when:

    * Organizational policy prohibits developers from having production access
    * You need a stable, read-only production environment
    * You want to preview full model and content state in a production context before going live
  </Accordion>

  <Accordion title="I have strict separation requirements for development, staging and production environments and/or handling environments across multiple geographic regions">
    **→ [Multiple instance deployment with multiple regions](/guides/deployment/multi-instance-multi-region)**

    For teams with data residency requirements or globally distributed operations, the multi-region pattern extends the two-instance architecture into a full matrix of environments and regions. It's the most operationally robust pattern — reserve it for situations where it's genuinely required.

    This is the right choice when:

    * Regulations require data to reside in specific geographic regions
    * You need DEV, STAGE, and PROD isolation across US, EU, and other regions simultaneously
    * Your team has the operational capacity to manage nine (or more) Omni instances
  </Accordion>
</AccordionGroup>

## How much review does your content need?

<AccordionGroup>
  <Accordion title="Minimal review (Agile teams)">
    Use standard Omni permissions — apply view, edit, and manage rights by folder and group. The [branch/publish workflow](/content/develop/branch-mode) provides a natural review gate without enforcing it.
  </Accordion>

  <Accordion title="High review (Waterfall teams)">
    Enable [**Require pull requests**](/integrations/git/settings) in git settings. This blocks direct commits to your default branch and requires all model changes to go through a PR. For content, you can additionally enable [**Require PR to publish**](/integrations/git/settings) at the document level — this prevents any published document from being updated without a reviewed PR.
  </Accordion>

  <Accordion title="Mixed review — some content 'can't break' (Agile and Waterfall teams)">
    Use document-level [**Require PR to publish**](/integrations/git/settings) selectively on your highest-stakes dashboards, while leaving standard draft/publish behavior on everything else.
  </Accordion>

  <Accordion title="High review — production environment is read-only (Waterfall teams)">
    Use a [multi-instance setup with git follower](/guides/deployment/multi-instance-prod-stage). Production users see only the promoted, validated state of your model and content.
  </Accordion>
</AccordionGroup>

## How do you manage database schema changes?

<AccordionGroup>
  <Accordion title="Additive changes on a single connection">
    Standard schema refresh works well. Use [soft refreshes](/modeling/develop/schema-refreshes) (additive only) for routine updates. Run a full [hard refresh](/modeling/develop/schema-refreshes) only when you need to remove references to dropped objects.
  </Accordion>

  <Accordion title="Schema changes with git branch protection enabled">
    Enable [**branch-based schema refresh**](/modeling/develop/schema-refreshes#requiring-branches-for-schema-refreshes) on your connection. This routes schema refreshes through a branch before they can be merged, preventing the force-push that a regular schema refresh would require.
  </Accordion>

  <Accordion title="Changes from a staging database">
    Open a branch, switch to your staging connection through [dynamic environments](/connect-data/dynamic-environments), trigger the schema refresh there, and validate before merging.
  </Accordion>

  <Accordion title="High-frequency programmatic schema updates">
    Use the [schema refresh API](/api/models/refresh-schema), [Agent Skills](/developers/agent-skills), or [CLI](/developers/cli) to trigger refreshes from your pipeline and for bulk model updates in a local IDE workflow.
  </Accordion>
</AccordionGroup>

## How should you scope data access across your team?

| Scenario                                                                 | Recommended approach                                                                                                  |
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| One data team, some row-level security                                   | [Single model](/guides/deployment/single-instance-git-dbt) with [access rules](/modeling/develop/data-access-control) |
| Multiple departments with shared core logic + department-specific fields | [Model extensions (shared extension models)](/modeling/develop/shared-extensions)                                     |
| Multi-tenant embedded analytics, one database, schemas per customer      | [Dynamic schemas](/connect-data/dynamic-environments)                                                                 |
| Multi-tenant embedded analytics, separate databases per customer         | [Dynamic connection environments](/connect-data/dynamic-environments)                                                 |
| Multi-region with data residency requirements                            | [Multiple Omni organizations](/guides/deployment/multi-instance-multi-region) (separate instances per region)         |
| Sensitive internal data that BI admins shouldn't see                     | Two separate Omni tenants                                                                                             |

## How do you structure both internal and embedded (external) users?

The right answer depends on whether internal and external users share the same data or need complete isolation:

* **Shared data, different access rules:** A single instance with user attributes and row-level security handles this well. Use [model extensions](/guides/deployment/scaled-deployments-shared-model-extensions) if external customers need customized views.
* **Separate databases per customer:** [Dynamic connection environments](/connect-data/dynamic-environments) plus model extensions is the standard embedded pattern.
* **Full isolation between internal and external:** Consider separate Omni instances for internal and embedded deployments, using [git follower](/integrations/git/follower-mode/index) to keep models in-sync.

## Decision tree summary

```mermaid theme={null}
%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '18px'}}}%%
flowchart LR
    A([Start]) --> B

    B{"Multiple Omni instances needed?"}

    B -->|No| C
    B -->|Yes| F

    C{"Separate staging database?"}

    C -->|Yes| D["Single instance + dynamic connections"]
    C -->|No| E["Single instance + git (+ dbt if applicable)"]

    F{"What is the scope?"}

    F -->|"Two instances (PROD / STAGE)"| G["Multi-instance PROD/STAGE with git follower"]
    F -->|"Multiple environments + regions"| H["Multi-instance multi-region"]

    style A fill:#272D6D,color:#fff,stroke:none

    style B fill:#272D6D,stroke:#3F4755,stroke-width:3px,color:#fff
    style C fill:#3F4755,stroke:#3F4755,stroke-width:3px,color:#fff
    style F fill:#3F4755,stroke:#3F4755,stroke-width:3px,color:#fff

    style D fill:#FF5789,color:#fff,stroke:none
    style E fill:#FF5789,color:#fff,stroke:none
    style G fill:#AA3F6B,color:#fff,stroke:none
    style H fill:#AA3F6B,color:#fff,stroke:none
```

## Deployment pattern guides

* [Single instance deployment with git and dbt](/guides/deployment/single-instance-git-dbt)
* [Single instance deployment with dynamic database environments](/guides/deployment/single-instance-dynamic-connections)
* [Multiple instance deployment with git follower (Prod/Stage)](/guides/deployment/multi-instance-prod-stage)
* [Multiple instance deployment across multiple regions](/guides/deployment/multi-instance-multi-region)
