The Apache Fory team is pleased to announce the 0.17.0 release. This is a major release that includes 71 PR from 19 distinct contributors. See the Install Page to learn how to get the libraries for your platform.
JavaScript/NodeJS Serialization: First Release
Apache Fory 0.17.0 marks the first release with official JavaScript/NodeJS
documentation, benchmark coverage, and TypeScript-friendly IDL code generation.
The JavaScript runtime is built for modern Node.js services and TypeScript
codebases, while preserving Fory's cross-language object model, schema-driven
APIs, and optional reference tracking.
Key capabilities:
- High-performance serialization for JavaScript and TypeScript objects in Node.js
- Cross-language compatibility with Java, Python, Go, Rust, C#, Swift, and Dart
- Schema-driven APIs via
Type.*builders and TypeScript decorators - Optional reference tracking for shared and circular object graphs
- Compatible mode for schema evolution
- Configurable depth, binary size, and collection size guardrails
- JavaScript/TypeScript target support in the Fory IDL/compiler workflow
- Optional
@apache-fory/hpsfast string path for Node.js 20+
Quick Start
import Fory, { Type } from "@apache-fory/core";
const userType = Type.struct(
{ typeName: "example.user" },
{
id: Type.int64(),
name: Type.string(),
age: Type.int32(),
},
);
const fory = new Fory();
const { serialize, deserialize } = fory.register(userType);
const bytes = serialize({
id: 1n,
name: "Alice",
age: 30,
});
const user = deserialize(bytes);
console.log(user);- JavaScript guide: https://fory.apache.org/docs/guide/javascript/
- Compiler docs: https://fory.apache.org/docs/compiler/
JavaScript Benchmarks
Below are throughput results (ops/sec; higher is better) comparing Fory with
Protocol Buffers and JSON across representative data structures.
| Datatype | Operation | Fory TPS | Protobuf TPS | JSON TPS | Fastest |
|---|---|---|---|---|---|
| Struct | Serialize | 8,453,950 | 1,903,706 | 3,058,232 | fory |
| Struct | Deserialize | 9,705,287 | 8,233,664 | 3,860,538 | fory |
| Sample | Serialize | 1,498,391 | 422,620 | 744,790 | fory |
| Sample | Deserialize | 1,918,162 | 819,010 | 762,048 | fory |
| MediaContent | Serialize | 1,293,157 | 729,497 | 1,299,908 | json |
| MediaContent | Deserialize | 1,638,086 | 1,209,140 | 921,191 | fory |
| StructList | Serialize | 3,928,325 | 495,648 | 891,810 | fory |
| StructList | Deserialize | 3,264,827 | 1,529,744 | 986,144 | fory |
| SampleList | Serialize | 355,581 | 92,741 | 163,120 | fory |
| SampleList | Deserialize | 424,916 | 163,253 | 162,520 | fory |
| MediaContentList | Serialize | 286,053 | 148,977 | 282,445 | fory |
| MediaContentList | Deserialize | 376,826 | 244,622 | 190,155 | fory |
Serialized data sizes (bytes):
| Datatype | Fory | Protobuf | JSON |
|---|---|---|---|
| Struct | 58 | 61 | 103 |
| Sample | 446 | 377 | 724 |
| MediaContent | 391 | 307 | 596 |
| StructList | 184 | 315 | 537 |
| SampleList | 1980 | 1900 | 3642 |
| MediaContentList | 1665 | 1550 | 3009 |
Benchmark details: https://github.com/apache/fory/tree/v0.17.0/benchmarks/javascript
Dart Serialization: First Release
Apache Fory 0.17.0 also marks the first release with official Dart
documentation, benchmark coverage, a rebuilt runtime, and Dart IDL support.
The Dart implementation focuses on generated serializers, stable
cross-language type identity, schema evolution, and predictable APIs for
service workloads.
Key capabilities:
- High-performance Dart serialization with generated code instead of reflection
- Cross-language compatibility with Java, Python, Go, Rust, C#, Swift, and JavaScript
@ForyStructand@ForyFieldannotations withbuild_runnercode generation- Compatible mode for schema evolution across versions
- Optional reference tracking for shared and circular object graphs
- Manual
Serializer<T>extension points for advanced or custom types - Dart target support in the Fory IDL/compiler workflow
Quick Start
import 'package:fory/fory.dart';
part 'person.fory.dart';
enum Color {
red,
blue,
}
@ForyStruct()
class Person {
Person();
String name = '';
Int32 age = Int32(0);
Color favoriteColor = Color.red;
}
void main() {
final fory = Fory();
PersonFory.register(
fory,
Color,
namespace: 'example',
typeName: 'Color',
);
PersonFory.register(
fory,
Person,
namespace: 'example',
typeName: 'Person',
);
final bytes = fory.serialize(Person()
..name = 'Ada'
..age = Int32(36)
..favoriteColor = Color.blue);
final roundTrip = fory.deserialize<Person>(bytes);
print(roundTrip.name);
}- Dart guide: https://fory.apache.org/docs/guide/dart/
- Compiler docs: https://fory.apache.org/docs/compiler/
Dart Benchmarks
Below are throughput results (ops/sec; higher is better) comparing Fory with
Protocol Buffers across representative data structures.
| Datatype | Operation | Fory TPS | Protobuf TPS | Fastest |
|---|---|---|---|---|
| Struct | Serialize | 3,989,432 | 1,884,653 | fory (2.12x) |
| Struct | Deserialize | 5,828,197 | 4,199,680 | fory (1.39x) |
| Sample | Serialize | 1,649,722 | 500,167 | fory (3.30x) |
| Sample | Deserialize | 2,060,113 | 785,109 | fory (2.62x) |
| MediaContent | Serialize | 800,876 | 391,235 | fory (2.05x) |
| MediaContent | Deserialize | 1,315,115 | 683,533 | fory (1.92x) |
| StructList | Serialize | 1,456,396 | 367,506 | fory (3.96x) |
| StructList | Deserialize | 1,921,006 | 645,958 | fory (2.97x) |
| SampleList | Serialize | 411,144 | 48,508 | fory (8.48x) |
| SampleList | Deserialize | 464,273 | 103,558 | fory (4.48x) |
| MediaContentList | Serialize | 186,870 | 77,029 | fory (2.43x) |
| MediaContentList | Deserialize | 330,293 | 128,215 | fory (2.58x) |
Serialized data sizes (bytes):
| Datatype | Fory | Protobuf |
|---|---|---|
| Struct | 58 | 61 |
| Sample | 446 | 377 |
| MediaContent | 365 | 307 |
| StructList | 184 | 315 |
| SampleList | 1980 | 1900 |
| MediaContentList | 1535 | 1550 |
Benchmark details: https://github.com/apache/fory/tree/v0.17.0/benchmarks/dart
Highlights
- refactor(java): refactor fory java serialization api by @chaokunyang in #3537
- refactor(python): refactor python serialization api by @chaokunyang in #3543
- feat(java): reduce java serializer memory usage by share across Fory instances by @chaokunyang in #3546
- feat(java): remove guava dependency from fory java by @chaokunyang in #3557
- refactor(dart): new dart implementation by @chaokunyang in #3551
Features
- refactor(javascript): rename apache-fory/fory to apache-fory/core by @chaokunyang in #3489
- feat(ci): add bazel downloads retry by @BaldDemian in #3492
- feat(go): add configurable size guardrails by @ayush00git in #3475
- refactor(ci): install Bazel using setup-bazel by @BaldDemian in #3494
- perf(rust): Rewrite Rust benchmarks around shared bench.proto data by @chaokunyang in #3497
- feat(cpp): add float16 to c++ by @UninspiredCarrot in #3487
- feat(java): add float support by @mengnankkkk in #3254
- feat(java): support java virtual threads by @chaokunyang in #3522
- perf(java): optimize thread safe fory for java by @chaokunyang in #3529
- test(cpp): optimize float16 sign symmetry test for ASAN by @Geethapranay1 in #3531
- feat(java): add dedicated exception serializers by @chaokunyang in #3536
- refactor(java): refactor fory java serialization api by @chaokunyang in #3537
- refactor(python): refactor python serialization api by @chaokunyang in #3543
- feat(dart): Introduce id based enum serialization by @yash-agarwa-l in #3482
- feat(javascript): add configurable size guardrails by @ayush00git in #3539
- feat(java): reduce java serializer memory usage by share across Fory instances by @chaokunyang in #3546
- refactor(javascript): move serialization runtime state into contexts by @chaokunyang in #3549
- refactor(swift): refine swift api by @chaokunyang in #3554
- feat(xlang): refine xlang api and enum serialization by @chaokunyang in #3555
- feat(java): remove guava dependency from fory java by @chaokunyang in #3557
- refactor(dart): new dart implementation by @chaokunyang in #3551
- feat(compiler): Add JavaScript/TypeScript IDL code generation by @miantalha45 in #3394
- perf(javascript): add javascript benchmark by @chaokunyang in #3562
- perf(dart): optimize struct deserialize with direct dispatch codegen by @yash-agarwa-l in #3563
- feat(dart): add dart IDL support by @chaokunyang in #3571
- feat(python): fix python struct xlang ref track error by @chaokunyang in #3574
- feat: make generate enum use id for wire format by @chaokunyang in #3576
Bug Fix
- fix(java): Restore compact codec fixed width optimizations by @stevenschlansker in #3478
- fix(rust): handle panics from fuzz-found edge cases by @utafrali in #3481
- fix(rust): add error handling logic for std duration; add support for chrono duration by @BaldDemian in #3490
- fix(compiler): validate rpc request/response types by @retryoos in #3493
- fix(c++): fix misaligned address access errors detected by UBSan in buffer.h by @BaldDemian in #3479
- fix(java): finalize codegen config hash on first use by @chaokunyang in #3495
- fix(rust): fix several panics detected by cargo-fuzz by @BaldDemian in #3483
- fix(java): handle private final map codegen by @chaokunyang in #3504
- fix(compiler): repair broken service example and add regression coverage by @VikingDeng in #3505
- fix(rust): deep clone TypeMeta to prevent UB in concurrent scenarios by @BaldDemian in #3511
- fix(compiler): fix failed tests in compiler; add compiler CI by @BaldDemian in #3516
- fix(compiler): allow qualified nested types in FDL rpc signatures by @VikingDeng in #3518
- fix(java): preserve ConcurrentSkipListSet comparator on copy by @mandrean in #3520
- test(compiler): add IR validation and codegen tests for gRPC service support by @darius024 in #3528
- fix(java): Correct resolution of dependent/nested serializers in GraalVM by @rakow in #3532
- fix(java): fix objectstream serializer async jit and graalvm support by @chaokunyang in #3534
- ci: fix Bazel cache paths for C++ workflows by @chaokunyang in #3535
- fix(python): fix wrong calling orders in visit_other by @BaldDemian in #3542
- fix(js): corrected the float64 array size by @ayush00git in #3541
- fix(java): configure type checker during build by @chaokunyang in #3550
- fix(java): auto-select child serializers for sorted containers by @chaokunyang in #3552
- fix(java): support skip optional sql serializers for java11+ by @chaokunyang in #3553
- fix(rust): apply consistent pascalcase naming for nested types by @utafrali in #3548
- fix(javascript): fix flaky javascript idl tests by @chaokunyang in #3565
- fix(swift): fix swift generated code compile warnings by @chaokunyang in #3566
- fix(java): add test for previous uncaught regression. by @PiotrDuz in #3573
Other Improvements
- chore(java): Update Spotless and Checkstyle to allow building with JDK25 by @stevenschlansker in #3476
- chore(java): Clean up Javadoc warnings, and fail the build if any new ones are introduced by @stevenschlansker in #3477
- chore: bump version to 0.16.0 by @chaokunyang in #3488
- docs: add python benchmark result to readme by @chaokunyang in #3496
- docs: fix benchmark plots by @chaokunyang in #3498
- docs: add fory code review skill by @chaokunyang in #3500
- chore: adjust skills softlinks by @chaokunyang in #3501
- chore(cpp): configure CI to extract and execute C++ code from Markdo… by @Tyooughtul in #3381
- docs: improve comments in Java generator by @codewithtarun2005 in #3507
- docs: refactor agents.md to reduce token usage by @chaokunyang in #3538
- docs: add ai-review policy by @chaokunyang in #3545
- chore: Bump org.apache.logging.log4j:log4j-core from 2.25.3 to 2.25.4 in /java/fory-test-core by @dependabot[bot] in #3556
- chore(javascript): rename ref tracking to ref by @chaokunyang in #3559
- docs(dart): add dart docs by @chaokunyang in #3560
- docs(javascript): add javascript docs by @chaokunyang in #3561
- docs: refine dart and javascript docs by @chaokunyang in #3567
- docs(dart): update dart benchmark docs by @yash-agarwa-l in #3568
- docs: update readme by @chaokunyang in #3575
New Contributors
- @utafrali made their first contribution in #3481
- @BaldDemian made their first contribution in #3490
- @retryoos made their first contribution in #3493
- @Tyooughtul made their first contribution in #3381
- @UninspiredCarrot made their first contribution in #3487
- @VikingDeng made their first contribution in #3505
- @codewithtarun2005 made their first contribution in #3507
- @darius024 made their first contribution in #3528
- @rakow made their first contribution in #3532
- @PiotrDuz made their first contribution in #3573
Full Changelog: v0.16.0...v0.17.0

