# How to Configure Build Profiles and Optimization Levels in Sway: A Complete Guide

> Learn to configure Sway build profiles and optimization levels in Forc.toml, disabling IR passes for faster builds or enabling full optimizations for production.

- Repository: [Fuel Labs/sway](https://github.com/FuelLabs/sway)
- Tags: how-to-guide
- Published: 2026-03-04

---

**Sway projects use `[build-profile]` tables in [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml) to bundle compiler flags and optimization levels, where `optimization_level = 0` disables IR passes for faster builds and `optimization_level = 1` enables full optimizations for production.**

The Sway compiler (`forc`) controls the compilation pipeline through build profiles defined in your project's manifest. By configuring these profiles, you can switch between rapid debug iterations with no optimizations and release builds that run aggressive IR passes to minimize bytecode size. This guide covers how to configure build profiles and optimization levels in Sway using the manifest format and CLI overrides, based on the actual implementation in the FuelLabs/sway repository.

## Understanding Build Profiles in Sway

A **build profile** is a named collection of compiler settings stored under `[build-profile.<name>]` in [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml). According to [`forc-pkg/src/manifest/build_profile.rs`](https://github.com/FuelLabs/sway/blob/main/forc-pkg/src/manifest/build_profile.rs), profiles deserialize into `BuildProfile` structs containing fields like `optimization_level`, `print_asm`, and `backtrace`.

The compiler automatically injects two default profiles—`debug` and `release`—if you don't define them explicitly. Each field controls a specific aspect of compilation, from AST printing to backtrace behavior.

Key fields include:

- `optimization_level`: Sets the `OptLevel` enum (`0` or `1`)
- `print_ir`: Configures IR output (initial, final, modified)
- `print_asm`: Controls assembly output stages
- `include_tests`: Determines whether test functions are compiled
- `terse`: Minimizes warning and error output

## Default Debug and Release Profiles

Sway provides two built-in profiles that serve as the baseline for all builds.

### Debug Profile (No Optimizations)

The `debug` profile defaults to `optimization_level = 0` (mapped to `OptLevel::Opt0` in [`sway-core/src/build_config.rs`](https://github.com/FuelLabs/sway/blob/main/sway-core/src/build_config.rs)), which skips all IR optimization passes for faster compilation. As implemented in [`forc-pkg/src/manifest/build_profile.rs`](https://github.com/FuelLabs/sway/blob/main/forc-pkg/src/manifest/build_profile.rs) at line 71, this profile prioritizes build speed and debugging information over performance.

Default debug configuration:

```toml
[build-profile.debug]
optimization_level = 0
print_asm = { virtual = false, allocated = false, final = true }
print_ir = { initial = false, final = true, modified = false, passes = [] }
terse = false
backtrace = "all_except_never"

```

### Release Profile (Full Optimizations)

The `release` profile sets `optimization_level = 1` (mapped to `OptLevel::Opt1`), enabling the full suite of IR optimization passes including dead-code elimination and SROA. This is defined at line 95 of [`forc-pkg/src/manifest/build_profile.rs`](https://github.com/FuelLabs/sway/blob/main/forc-pkg/src/manifest/build_profile.rs).

Default release configuration:

```toml
[build-profile.release]
optimization_level = 1
print_asm = { virtual = true, allocated = false, final = true }
print_ir = { initial = true, final = false, modified = true, passes = ["dce", "sroa"] }
terse = true
backtrace = "only_always"

```

## Creating Custom Build Profiles

You can define additional profiles under `[build-profile.<custom_name>]` in [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml). Custom profiles inherit unspecified fields from the default `debug` profile, as handled by the merge logic in [`forc-pkg/src/manifest/mod.rs`](https://github.com/FuelLabs/sway/blob/main/forc-pkg/src/manifest/mod.rs) around line 820.

Example custom profile for optimized testing:

```toml
[build-profile.fast-test]
optimization_level = 1
include_tests = true
terse = true
print_ir = { final = true, modified = true, passes = [] }

```

To use a custom profile, run:

```bash
forc build --build-profile fast-test

```

## Understanding Optimization Levels

The `optimization_level` field maps directly to the `OptLevel` enum defined in [`sway-core/src/build_config.rs`](https://github.com/FuelLabs/sway/blob/main/sway-core/src/build_config.rs) (lines 48-53):

```rust
pub enum OptLevel {
    #[default] Opt0 = 0, // No IR passes
    Opt1 = 1,            // Run all optimization passes
}

```

During compilation in [`sway-core/src/lib.rs`](https://github.com/FuelLabs/sway/blob/main/sway-core/src/lib.rs) (lines 469-479), the compiler checks this enum to determine whether to skip optimizations or run the full `PassManager::run_all_passes` routine.

- **Opt0 (`optimization_level = 0`)**: IR passes straight to code generation. Use this for faster builds during development.
- **Opt1 (`optimization_level = 1`)**: Runs all optimization passes, producing smaller and more efficient bytecode for production deployment.

## Overriding Profiles via CLI

CLI flags take precedence over [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml) settings, allowing temporary adjustments without editing the manifest.

Key flags:

- `--release`: Selects the `release` profile (equivalent to `optimization_level = 1`)
- `--build-profile <name>`: Uses a specific custom profile
- `--opt-level <0|1>`: Directly overrides the optimization level
- `--asm <virtual|allocated|final|all>`: Overrides `print_asm` settings
- `--ir <initial|final|modified>`: Overrides `print_ir` settings

For example, to build with release settings but disable optimizations temporarily:

```bash
forc build --release --opt-level 0

```

## Practical Configuration Example

Here's a complete [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml) demonstrating multiple profiles:

```toml
[project]
name = "my_contract"
authors = ["Alice"]
license = "Apache-2.0"
entry = "main.sw"

[build-profile.debug]
optimization_level = 0
terse = false

[build-profile.release]
optimization_level = 1
terse = true

[build-profile.ci]
optimization_level = 1
include_tests = true
error_on_warnings = true
terse = true

```

Build commands:

```bash

# Standard debug build (Opt0)

forc build

# Optimized release build (Opt1)

forc build --release

# CI-optimized build with tests

forc build --build-profile ci

# Quick optimization test without editing files

forc build --opt-level 1 --ir final

```

## Summary

- Build profiles in Sway are defined as `[build-profile.<name>]` tables in [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml) and deserialized into `BuildProfile` structs in [`forc-pkg/src/manifest/build_profile.rs`](https://github.com/FuelLabs/sway/blob/main/forc-pkg/src/manifest/build_profile.rs).
- The `optimization_level` field accepts `0` (Opt0, no IR passes) or `1` (Opt1, full optimizations), mapping to the `OptLevel` enum in [`sway-core/src/build_config.rs`](https://github.com/FuelLabs/sway/blob/main/sway-core/src/build_config.rs).
- Default `debug` and `release` profiles are automatically injected if missing, with `debug` defaulting to level 0 and `release` to level 1.
- Custom profiles inherit missing fields from the base `debug` profile, allowing partial overrides.
- CLI flags like `--release`, `--opt-level`, and `--build-profile` override manifest settings for temporary configuration changes.

## Frequently Asked Questions

### What is the difference between Opt0 and Opt1 in Sway?

Opt0 (`optimization_level = 0`) skips all IR optimization passes, resulting in faster compilation times but larger bytecode. Opt1 (`optimization_level = 1`) runs the full optimization suite including dead-code elimination and SROA, producing smaller, more efficient bytecode suitable for production. These correspond to the `OptLevel::Opt0` and `OptLevel::Opt1` variants in [`sway-core/src/build_config.rs`](https://github.com/FuelLabs/sway/blob/main/sway-core/src/build_config.rs).

### How do I create a custom build profile in Sway?

Add a `[build-profile.<name>]` table to your [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml) file and specify only the fields you want to override. Unspecified fields inherit values from the default `debug` profile. For example, `[build-profile.fast]` with `optimization_level = 1` and `include_tests = true` creates an optimized test build. Activate it with `forc build --build-profile fast`.

### Can I override optimization levels from the command line?

Yes. Use the `--opt-level <0|1>` flag to temporarily override the `optimization_level` specified in your profile. You can also use `--release` to select the release profile (which sets level 1) or `--build-profile <name>` to select a custom profile. CLI flags always take precedence over [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml) settings.

### Where are the default debug and release profiles defined?

The default values for `debug` and `release` profiles are hardcoded in [`forc-pkg/src/manifest/build_profile.rs`](https://github.com/FuelLabs/sway/blob/main/forc-pkg/src/manifest/build_profile.rs), specifically in the `BuildProfile::debug()` method at line 71 and `BuildProfile::release()` at line 95. If these tables are missing from your [`Forc.toml`](https://github.com/FuelLabs/sway/blob/main/Forc.toml), the compiler automatically injects them before processing, as ensured by the logic in [`forc-pkg/src/manifest/mod.rs`](https://github.com/FuelLabs/sway/blob/main/forc-pkg/src/manifest/mod.rs) around line 820.