BYTEA

How to use the PostgreSQL BYTEA data type to store binary data: hex and escape formats, inserting and retrieving binary strings, and when to use BYTEA versus external file storage.

4 min read · Last updated: March 2026 · Back to overview

Quick Answer

The PostgreSQL BYTEA (binary array) data type stores variable-length binary strings — raw byte sequences up to 1 GB. Use BYTEA for small binary objects like thumbnails, cryptographic hashes, or certificates. For large files, store them externally and save the path in the database.

Spin up a Postgres database in 20 seconds with Vela.

Try Vela Sandbox

Introduction to the PostgreSQL BYTEA data type

BYTEA (binary array) stores variable-length sequences of bytes — raw binary data including null bytes and non-printable characters. Maximum size is 1 GB per column value.

Declare a BYTEA column with:

column_name BYTEA

Common use cases: storing cryptographic hashes, digital signatures, encrypted values, small images or thumbnails, and binary file content for small files.

Creating a table and inserting binary data

CREATE TABLE binary_data (
  id   INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  data BYTEA
);

-- Insert using hex format (recommended)
INSERT INTO binary_data (data) VALUES ('2345');

-- Retrieve the data
SELECT * FROM binary_data;

-- Output:
-- id |   data
-- ---+----------
--  1 | 2345

BYTEA output formats

PostgreSQL supports two output formats for BYTEA. The default is hex format:

-- Hex format (default)
SET bytea_output = 'hex';
SELECT 'H656c6c6f'::bytea;
-- H656c6c6f

-- Escape format (older style)
SET bytea_output = 'escape';
SELECT 'H656c6c6f'::bytea;
-- Hello

Common BYTEA functions

-- Get length in bytes
SELECT octet_length('H656c6c6f'::bytea);
-- 5

-- Concatenate two BYTEA values
SELECT 'H65'::bytea || 'l6c6f'::bytea;
-- H656c6c6f

-- Extract a slice (1-based offset)
SELECT substring('H656c6c6f'::bytea FROM 1 FOR 3);
-- H656c

-- Encode to Base64 text
SELECT encode('H656c6c6f'::bytea, 'base64');
-- SGVsbG8=

-- Decode from Base64 back to BYTEA
SELECT decode('SGVsbG8=', 'base64');
-- H656c6c6f

Storing a hash in BYTEA

CREATE TABLE api_keys (
  id         SERIAL PRIMARY KEY,
  key_hash   BYTEA NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- Store a SHA-256 hash of an API key
INSERT INTO api_keys (key_hash)
VALUES (decode(md5('my-secret-key'), 'hex'));

-- Look up by hash
SELECT id, created_at
FROM api_keys
WHERE key_hash = decode(md5('my-secret-key'), 'hex');

Production tips

  • For files larger than a few megabytes, store them in object storage (S3, GCS) and save the URL or path in a VARCHAR column — BYTEA at that scale increases backup size and memory pressure.
  • Use parameterized queries when inserting binary data from application code — your database driver handles proper encoding without manual hex escaping.
  • Use encode(data, 'base64') when you need to return binary data as a text payload in an API response.
  • For cryptographic hashes, use SHA-256 or stronger instead of MD5 — PostgreSQL provides digest(data, 'sha256') in the pgcrypto extension.

Reference: PostgreSQL documentation — Binary data types.

Continue in PostgreSQL Data Types: Composite Types.

Related in this section: Boolean · CHAR, VARCHAR, and TEXT · NUMERIC

Frequently Asked Questions

What is the PostgreSQL BYTEA data type?

BYTEA stands for binary array. It stores variable-length sequences of bytes — any binary data including non-printable characters and null bytes. The maximum size is 1 GB. PostgreSQL displays BYTEA values in hex format by default (e.g. \x012345) but also supports an older escape format.

What is the difference between the hex and escape formats for BYTEA?

The hex format (default since PostgreSQL 9.0) represents each byte as two hexadecimal digits: \x0123ABCD. The escape format uses printable ASCII for printable bytes and octal escape sequences (\NNN) for non-printable ones. The hex format is more compact and unambiguous. Control the output format with: SET bytea_output = 'hex'; or SET bytea_output = 'escape';

How do you insert binary data into a BYTEA column?

Use hex literals with the \x prefix: INSERT INTO binary_data (data) VALUES ('\x012345'); In application code, use parameterized queries with binary buffers — your database driver handles the encoding. Avoid constructing binary literals by string concatenation, as this is error-prone.

How do you read and manipulate BYTEA values in PostgreSQL?

PostgreSQL provides functions including: length(bytea) for byte count, substring(bytea FROM int FOR int) for slicing, bytea || bytea for concatenation, encode(bytea, 'base64') to convert to Base64 text, and decode('base64string', 'base64') to convert back. You can also use octet_length() to get the byte count.

When should I store files in BYTEA versus the filesystem?

Use BYTEA for small binary data (up to a few megabytes): cryptographic hashes, digital signatures, small thumbnails, encrypted secrets, or TLS certificates. For larger files, store them externally (object storage, filesystem) and save the file path or URL in a VARCHAR column. Large BYTEA values trigger PostgreSQL TOAST storage and increase backup and replication overhead.