Skip to content

[Feature Request]: Support random access in the Go Filesystem API (io.ReaderAt / io.ReadSeeker) #39176

Open

Description

@mdreizin

What would you like to happen?

The Go Filesystem API should support random access when the underlying filesystem provides it.

Currently, filesystem.Interface.OpenRead returns an io.ReadCloser, which only supports sequential reads. This makes it difficult to implement readers for file formats such as Parquet, ORC, Arrow IPC, and similar formats that rely on seeking to arbitrary offsets within a file.

Although storage backends such as GCS, S3, and local files support range reads or random access, that capability is not exposed through the Go Filesystem abstraction. As a result, implementations either need to buffer the entire file into memory or bypass the Beam Filesystem API and use storage-specific clients directly.

It would be useful if the Go Filesystem API exposed a random access interface, for example by returning an io.ReaderAt, io.ReadSeeker, or another abstraction that supports efficient seeking when the underlying filesystem is capable of it.

This would make it easier to build portable, efficient Beam I/O connectors and readers for columnar and indexed file formats without sacrificing performance or bypassing the Beam filesystem abstraction.

Issue Priority

Priority: 2 (default / most feature requests should be filed as P2)

Issue Components

  • Component: Python SDK
  • Component: Java SDK
  • Component: Go SDK
  • Component: Typescript SDK
  • Component: IO connector
  • Component: Beam YAML
  • Component: Beam examples
  • Component: Beam playground
  • Component: Beam katas
  • Component: Website
  • Component: Infrastructure
  • Component: Spark Runner
  • Component: Flink Runner
  • Component: Prism Runner
  • Component: Twister2 Runner
  • Component: Hazelcast Jet Runner
  • Component: Google Cloud Dataflow Runner

Activity

  1. Gaurav598 commented on Sep 1, 2026

    @Gaurav598
    Contributor

    I did a repository-level investigation of this issue to understand the current Go filesystem architecture and possible API designs.

    A few findings that may be useful for whoever works on this:

    • filesystem.Interface.OpenRead currently returns io.ReadCloser, so the Beam abstraction only exposes sequential reads.
    • The existing filesystem architecture already uses optional capability interfaces such as Copier, Renamer, and Remover, which makes an additive optional random-access capability a natural fit.
    • The local filesystem currently exposes an *os.File only as an io.ReadCloser, even though the underlying file supports positional reads/seeking.
    • memfs similarly uses a bytes.Reader, whose random-access capabilities are currently hidden by the io.ReadCloser abstraction.
    • The GCS and S3 implementations currently expose streaming readers, while their underlying storage APIs provide range-read primitives.
    • Changing OpenRead directly to io.ReaderAt or io.ReadSeeker would be a breaking API change for existing filesystem implementations.
    • From the storage semantics, positional/range reads appear to map more naturally to object storage than a stateful io.ReadSeeker.

    The main design question seems to be whether the optional capability should expose an io.ReaderAt-style interface with explicit lifecycle semantics, or a Beam-specific range-read abstraction that maps directly to remote range requests.

    I also noticed that parquetio currently reads the entire file into memory before passing it to the Parquet reader, which is a concrete downstream example of the limitation described in this issue.

    I hope these findings are useful to whoever takes this issue forward.

  2. goutamadwant commented on Sep 27, 2026

    @goutamadwant
    Contributor

    @mdreizin is an optional io.ReaderAt interface with a buffered fallback the right approach here? I can put together the API and filesystem tests. Let me know. thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions