---
title: "Code Ranges: A Deeper Look at Ruby Strings"
description: "Ruby's string model supports mutable and immutable operations, per-object or per-file freezing, and more than 100 encodings, while permitting byte sequences invalid for their attached encoding. This flexibility helps legacy and unusual platforms but makes encoding checks, validity scans, and character-boundary handling part of many operations. To reduce repeated O(n) validation scans, Ruby implementations cache each string's state in a four-valued code range: unknown, 7bit, valid, or broken. The post explains how these values map to public methods, how MRI stores them in two header bits, and how JRuby and TruffleRuby represent them differently. It also describes code ranges as inputs to fast and slow paths and as useful but fallible cache information, especially for native extensions and string-heavy metaprogramming."
---

# Code Ranges: A Deeper Look at Ruby Strings

[Shopify](https://yomu.fyi/company/shopify) · 2023-10-18 · Apr 14, 2022

**Type:** Explainer

## Summary

Ruby's string model supports mutable and immutable operations, per-object or per-file freezing, and more than 100 encodings, while permitting byte sequences invalid for their attached encoding. This flexibility helps legacy and unusual platforms but makes encoding checks, validity scans, and character-boundary handling part of many operations. To reduce repeated O(n) validation scans, Ruby implementations cache each string's state in a four-valued code range: unknown, 7bit, valid, or broken. The post explains how these values map to public methods, how MRI stores them in two header bits, and how JRuby and TruffleRuby represent them differently. It also describes code ranges as inputs to fast and slow paths and as useful but fallible cache information, especially for native extensions and string-heavy metaprogramming.

## Context

Ruby strings combine mutability, freezing, many possible encodings, and the ability to hold byte sequences invalid for an attached encoding. Determining validity or character boundaries can require scanning the string, creating runtime overhead in string operations and in Ruby's broader metaprogramming machinery.

## Approach / What changed

The post examines code ranges as cached per-string information, covering the four values, their mapping to public Ruby methods, MRI's compact two-bit representation, and differing representations in JRuby and TruffleRuby. It also discusses how code ranges guide optimized and slow paths and how incorrect cache maintenance can affect correctness.

## Takeaways

- Ruby code ranges have four mutually exclusive values: ENC\_CODERANGE\_UNKNOWN, ENC\_CODERANGE\_7BIT, ENC\_CODERANGE\_VALID, and ENC\_CODERANGE\_BROKEN.
- MRI stores a string's code range in two object-header bits, so the constants must be compared as enum-like values rather than combined or tested directly as bitmasks.
- Code ranges can avoid repeated string scans, but native extensions that fail to update them properly can leave cached information wrong and cause correctness or performance issues.

**Tags:** [Architecture](https://yomu.fyi/topic/architecture), [Performance](https://yomu.fyi/topic/performance), [Reliability](https://yomu.fyi/topic/reliability)

- Source: [Shopify](https://shopify.engineering/code-ranges-ruby-strings)
- Source URL: https://shopify.engineering/code-ranges-ruby-strings
- Ingested by Yomu: 2026-08-30T15:26:52.538Z

[Read original post](https://shopify.engineering/code-ranges-ruby-strings)
