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

# Best Practices

> Common patterns for organizing environments and packages, and for versioning releases

The [Environments](/how-to/modeling/environment-overview) page covered what environments and packages are. This page is about how many to create and where to draw the boundaries — the organizational patterns that scale, and the versioning habits that keep releases safe.

Everything below builds on two properties from the overview: **connections are shared** by every package in an environment, and **packages are versioned** with one version pinned as latest.

## Environment Patterns

An environment maps to whatever boundary your organization wants a stable, separately-governed configuration around. Three patterns cover most teams — and they compose.

### Pattern 1: Department or Team Environments

Give each department or team — finance, HR, RevOps, marketing — its own environment, with the connections, packages, and access that team owns. This mirrors how data and responsibility are already split across your organization.

```
Organization: acme-corp
├── Environment: finance
│   ├── Connection: finance-warehouse
│   └── Packages: gl-model, revenue-model
├── Environment: revops
│   ├── Connection: salesforce-warehouse
│   └── Packages: pipeline-model, quota-model
└── Environment: hr
    ├── Connection: workday-warehouse
    └── Packages: headcount-model
```

**When to use:**

* Departments own distinct data sources and databases
* Access should be scoped to each team (finance data stays with finance)
* Teams model and publish independently, on their own cadence

**Benefits:**

* Access control follows your org structure — [grant a team access](/platform-admin/permissions#sharing-environments--packages) to its environment
* Connections are isolated per department, so one team's data isn't exposed to another
* Each team can hold multiple packages that share the environment's connections

### Pattern 2: Development-Stage Environments

Use separate environments for the stages of your delivery lifecycle — development, staging, and production — and optionally a **private environment per developer** for isolated iteration.

```
Organization: acme-corp
├── Environment: analytics-dev
│   ├── Connection: dev-snowflake (→ dev.snowflake.com)
│   └── Package: sales-model v1.3.0
├── Environment: analytics-staging
│   ├── Connection: staging-snowflake (→ staging.snowflake.com)
│   └── Package: sales-model v1.3.0
├── Environment: analytics-prod
│   ├── Connection: prod-snowflake (→ prod.snowflake.com)
│   └── Package: sales-model v1.2.0
└── Environment: analytics-jdoe (private)
    ├── Connection: dev-snowflake
    └── Package: sales-model (work in progress)
```

**When to use:**

* You have different database connections for each stage
* You want to test models against non-production data before promoting
* Individual developers need a sandbox that won't disturb shared environments

**Workflow:**

1. Iterate in a private (or `dev`) environment against dev connections
2. Publish and test a new version in `dev`, then promote it to `staging`
3. After validation, publish to `prod` and pin as latest

### Pattern 3: Hybrid (Department × Stage)

Combine the two: give each department its own set of stage environments. This is common once several teams each need an independent delivery lifecycle.

```
Organization: acme-corp
├── Environment: finance-dev
├── Environment: finance-prod
├── Environment: revops-dev
└── Environment: revops-prod
```

**When to use:**

* Multiple departments each own their data *and* need dev/prod separation
* Teams promote changes independently without coordinating a shared release

**Keep it as simple as it needs to be.** More environments means more configurations to govern. Start with the boundary that matters most — a department split or a stage split — and add the second axis only when a team actually needs it. Within any environment you can hold multiple packages that share its connections, and use [versioning](#versioning-best-practices) to manage releases without adding environments.

## Versioning Best Practices

### Version Numbering

Use semantic versioning in `publisher.json`:

```json theme={"languages":{"custom":["/languages/motly.tmGrammar.json","/languages/malloy.tmGrammar.json"]}}
{
  "name": "sales-model",
  "version": "1.2.3",
  "description": "Sales analytics semantic model"
}
```

* **Major (1.x.x)**: Breaking changes (rename fields, remove views)
* **Minor (x.2.x)**: New features (add dimensions, new views)
* **Patch (x.x.3)**: Bug fixes, documentation

### Publish, Validate, Promote

Every publish creates a new immutable version, and the version pinned as **latest** is what consumers get by default — see [Publishing](/how-to/modeling/publishing) for the mechanics, including auto-promote and auto-archive. The safe release habit is a two-step process:

1. **Publish & validate**: Publish the new version without pinning. Test and validate with a small group who explicitly request the new version.
2. **Pin as latest**: Once validated, pin the version as latest to serve it to everyone as the default.

And archive versions you no longer serve — Credible garbage-collects the materialized tables and indexes that only unarchived versions reference, which keeps storage costs down.

## Next Steps

Your environment structure is settled — start building, or go deeper on governance:

<CardGroup cols={3}>
  <Card title="Modeling Overview" icon="wand-magic-sparkles" color="#5C7A93" href="/how-to/modeling/ai-modeling">
    Start building semantic models with your agent
  </Card>

  <Card title="Permissions" icon="lock" color="#94793A" href="/platform-admin/permissions">
    Learn how permissions work across environments and packages
  </Card>

  <Card title="CI/CD Setup" icon="rocket" color="#94793A" href="/platform-admin/cicd">
    Automate deployments with CI/CD workflows
  </Card>
</CardGroup>
