| --- |
| title: Configuration |
| sidebar_position: 4 |
| id: configuration |
| license: | |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --- |
| |
| This page covers C++ Fory instance configuration. `Fory::builder()` creates xlang |
| payloads by default. Compatible mode is also enabled by default. Select native |
| mode only when the payload stays in C++. |
| |
| ## Builder Pattern |
| |
| Use `Fory::builder()` to construct Fory instances with custom configuration: |
| |
| ```cpp |
| #include "fory/serialization/fory.h" |
| |
| using namespace fory::serialization; |
| |
| // Default xlang mode. |
| auto fory = Fory::builder().build(); |
| |
| // Native mode for C++-only payloads. |
| auto fory = Fory::builder() |
| .xlang(false) |
| .build(); |
| |
| // Same-schema optimization. Use only when every reader and writer |
| // always uses the same schema. |
| auto fory = Fory::builder() |
| .compatible(false) |
| .build(); |
| ``` |
| |
| ## Configuration |
| |
| ### xlang(bool) |
| |
| Select the wire mode. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .xlang(false) |
| .build(); |
| ``` |
| |
| When `true`, C++ writes the xlang wire format used by Java, Python, Go, Rust, |
| JavaScript/TypeScript, C#, Swift, Dart, Scala, and Kotlin. When `false`, C++ |
| writes native-mode payloads for C++-only traffic. |
| |
| **Default:** `true` |
| |
| ### compatible(bool) |
| |
| Compatible mode is enabled by default. No builder call is required for the |
| default compatible mode. Set `.compatible(false)` only when every reader and |
| writer always uses the same schema and you want faster serialization and smaller |
| size. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .compatible(false) |
| .build(); |
| ``` |
| |
| For xlang payloads, use `.compatible(false)` only after verifying that every language uses the same schema, or when native types are generated from Fory schema IDL. |
| |
| **Default:** `true` |
| |
| ### track_ref(bool) |
| |
| Enable/disable reference tracking for shared and circular references. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .track_ref(true) // Enable reference tracking |
| .build(); |
| ``` |
| |
| When enabled, avoids duplicating shared objects and handles cycles. |
| |
| **Default:** `true` |
| |
| ### max_graph_memory_bytes(int64_t) |
| |
| Set an approximate graph-memory gate for one root deserialization. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .max_graph_memory_bytes(64 * 1024 * 1024) |
| .build(); |
| ``` |
| |
| The default limit is a fixed `128 MiB` for byte-array, `Buffer`, and stream |
| roots. Positive values override the default. Explicit non-positive values are |
| rejected when the runtime is created. |
| |
| This budget is an approximate lower-bound estimate for materialized graph |
| owners, mainly collections, maps, arrays, structs, and objects. It is not an |
| exact process heap limit; actual process memory can be higher. Dedicated |
| string, binary, primitive scalar, and primitive dense-array leaf values are |
| skipped by this budget and continue to rely on byte-availability checks: if the |
| unread input does not contain enough bytes, Fory will not read or create that |
| leaf value. |
| |
| **Default:** `128 MiB` |
| |
| ### max_dyn_depth(uint32_t) |
| |
| Set maximum allowed nesting depth for dynamically-typed objects. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .max_dyn_depth(10) // Allow up to 10 levels |
| .build(); |
| ``` |
| |
| This limits the maximum depth for nested polymorphic object serialization (e.g., `shared_ptr<Base>`, `unique_ptr<Base>`). This prevents stack overflow from deeply nested structures in dynamic serialization scenarios. |
| |
| **Default:** `5` |
| |
| **When to adjust:** |
| |
| - **Increase**: For legitimate deeply nested data structures |
| - **Decrease**: For stricter security requirements or shallow data structures |
| |
| ### max_schema_versions_per_type(uint32_t) |
| |
| Set the maximum accepted remote metadata versions for one logical type. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .max_schema_versions_per_type(10) |
| .build(); |
| ``` |
| |
| **Default:** `10` |
| |
| ### max_type_fields(uint32_t) |
| |
| Set the maximum fields accepted in one received remote struct metadata body. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .max_type_fields(512) |
| .build(); |
| ``` |
| |
| **Default:** `512` |
| |
| ### max_type_meta_bytes(uint32_t) |
| |
| Set the maximum encoded body bytes accepted for one received TypeDef body, |
| excluding the 8-byte header and any extended-size varint. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .max_type_meta_bytes(4096) |
| .build(); |
| ``` |
| |
| **Default:** `4096` |
| |
| ### max_average_schema_versions_per_type(uint32_t) |
| |
| Set the average accepted remote metadata versions across accepted remote types. |
| The effective global floor is `8192` schemas. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .max_average_schema_versions_per_type(3) |
| .build(); |
| ``` |
| |
| **Default:** `3` |
| |
| ### check_struct_version(bool) |
| |
| Enable/disable struct version checking. |
| |
| ```cpp |
| auto fory = Fory::builder() |
| .compatible(false) |
| .check_struct_version(true) // Enable version checking |
| .build(); |
| ``` |
| |
| When enabled, validates type hashes to detect schema mismatches. |
| |
| **Default:** `false` |
| |
| ## Thread-Safe vs Single-Threaded |
| |
| ### Single-Threaded (Fastest) |
| |
| ```cpp |
| auto fory = Fory::builder().build(); // Returns Fory |
| ``` |
| |
| Single-threaded `Fory` is the fastest option, but NOT thread-safe. Use one instance per thread. |
| |
| ### Thread-Safe |
| |
| ```cpp |
| auto fory = Fory::builder().build_thread_safe(); // Returns ThreadSafeFory |
| ``` |
| |
| `ThreadSafeFory` uses a pool of Fory instances to provide thread-safe serialization. Slightly slower due to pool overhead, but safe to use from multiple threads concurrently. |
| |
| ## Configuration Summary |
| |
| | Option | Description | Default | |
| | ------------------------------------------------ | ------------------------------------------------- | --------- | |
| | `xlang(bool)` | Use xlang mode | `true` | |
| | `compatible(bool)` | Enable schema evolution | `true` | |
| | `track_ref(bool)` | Enable reference tracking | `true` | |
| | `max_graph_memory_bytes(int64_t)` | Approximate graph-memory gate per root read | `128 MiB` | |
| | `max_dyn_depth(uint32_t)` | Maximum nesting depth for dynamic types | `5` | |
| | `max_type_fields(uint32_t)` | Max fields in one received struct metadata body | `512` | |
| | `max_type_meta_bytes(uint32_t)` | Max encoded bytes in one received metadata body | `4096` | |
| | `max_schema_versions_per_type(uint32_t)` | Max remote metadata versions for one logical type | `10` | |
| | `max_average_schema_versions_per_type(uint32_t)` | Average remote metadata versions across types | `3` | |
| | `check_struct_version(bool)` | Enable struct version checking | `false` | |
| |
| ## Security |
| |
| Security-related configuration: |
| |
| - Register all structs and polymorphic implementations before deserializing untrusted payloads. |
| - Use `check_struct_version(true)` with `compatible(false)` for intentional same-schema payloads. |
| - Keep `max_graph_memory_bytes(...)` at the fixed `128 MiB` default for most inputs, or set a |
| positive value for a trusted workload that needs a different collection/map/struct gate. |
| - Keep `max_dyn_depth(...)` as low as your model permits to reject unexpectedly deep polymorphic |
| graphs. |
| - Keep the remote schema metadata limits at their defaults unless the data is not malicious and a |
| trusted peer sends larger metadata or many schema versions. |
| - Prefer concrete fields over broad polymorphic fields for untrusted input. |
| |
| ## Related Topics |
| |
| - [Basic Serialization](basic-serialization.md) - Using configured Fory |
| - [Xlang Serialization](xlang-serialization.md) - xlang mode details |
| - [Type Registration](type-registration.md) - Registering types |