All notable changes to beam_export will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[0.1.0] - 2026-11-07
First public release.
Added
- Exports from any
Enumerableor{Repo, queryable}Ecto source:BeamExport.to_file/3: atomic file writes (temporary file,fsync, rename), optional streaming gzip (compress: trueor a.gzpath), files created with mode0600(:file_mode).BeamExport.to_iodata/2: in-memory exports for small datasets.BeamExport.to_stream/2: lazy stream of CSViodatachunks.
- Plug/Phoenix downloads (
BeamExport.Plug, requires:plug):send_staged_export/4writes the export to a private (0700) temporary directory, releases the database connection, then serves the file withsend_file. Temporary files are removed when the request process exits.send_chunked_export/4streams with chunked transfer encoding and stops reading the source when the client disconnects.
- CSV encoding: RFC 4180 quoting, custom separators,
"\r\n"or"\n"line terminators. Exact floats (Float.to_string/1), decimals in plain notation, ISO 8601 dates and times, tuple rows (Ectoselect: {...}), and map/struct records read by:headers. - Formula injection protection, enabled by default (
sanitize_formulas: true), following the OWASP recommendation. - Ecto integration: cursor streaming with
:max_rowsbatches; eager rejection of preloads (BeamExport.PreloadError); reuses the caller's transaction when there is one; usesRepo.transact/2on Ecto 3.13+ andRepo.transaction/2before. - Errors:
BeamExport.MappingError,BeamExport.EncodeError,BeamExport.TimeoutError,BeamExport.ExportError,BeamExport.PreloadError. Record contents are redacted by default (:include_record_in_errorsopts in). - Option validation: unknown options and invalid values raise
ArgumentError. Telemetry:
[:beam_export, :export, :start | :chunk | :stop | :exception]events fromto_file/3andto_iodata/2. Exception metadata is always redacted.
Behaviour notes
These describe guarantees that a pre-release audit found missing in earlier development snapshots:
- An export that does not complete is never reported as successful. This covers
stalled consumers (
:consumer_timeout), unresponsive databases (:batch_timeout), failed commits, crashed workers, and write errors reported only when a file is closed (for example a full disk). - A failed export never deletes a file it did not create or truncate, and never deletes non-regular files.
meta.rowscounts the header row.