Encrypted Doesn’t Always Mean Verified: YSQL vs. YCQL TLS

You start a secure YugabyteDB cluster. Your YSQL connection succeeds with sslmode=require. Your YCQL shell connection asks for a CA certificate.

Why the difference? And does the successful YSQL connection mean certificate verification happened automatically?

The difference is in the client configuration and the checks it performs. TLS encryption, server identity verification, and database login are separate parts of the connection.

Let’s demonstrate this using an actual local test on YugabyteDB 2026.1.2.0, then look at how to configure trust deliberately.

First, What Is the CA File For?

ComponentWhat it does
TLS encryptionProtects traffic between the client and the endpoint with which it establishes TLS.
Server certificate verificationChecks the server certificate against a trusted CA; hostname verification additionally checks that it belongs to the endpoint you requested.
Database authenticationChecks who is connecting, such as a username and password.
Client certificate authentication / mutual TLSUses a client certificate and its private key when the server requires them. This is separate from trusting the server’s CA.
💡 A trust anchor, not a login credential: The client reads ca.crt locally to validate the server’s certificate chain. Supplying that file does not mean presenting a client certificate to the database. A CA certificate is public material; CA and node private keys must remain protected.

Demo: Same Cluster, Different Client Settings

The commands below use yugabyted, ysqlsh, and ycqlsh from PATH. If your binaries are not on PATH, use their actual installation paths.

Connection commands have been adjusted to prompt for passwords instead of putting passwords in shell history or process arguments. The connection messages are excerpts from the supplied run.

1. Start a Secure Local Universe

On a fresh local test installation:

				
					yugabyted start --secure
				
			

The startup output confirmed encryption in transit and password authentication, with a single-node RF1 universe.

For this run, the generated credentials file was:

				
					/root/var/data/yugabyted_credentials.txt
				
			

Read the generated credentials privately and enter the corresponding password when prompted. 

Along with the login credentials, yugabyted --secure generated the TLS certificates for this local universe. In this installation, they are stored in /root/var/certs.

Let’s list those files so we can identify the CA certificate needed for the YCQL connection later in the demo:

				
					ls /root/var/certs
				
			

Actual result:

				
					ca.crt  node.127.0.0.1.crt  node.127.0.0.1.key
				
			

The file we will use is ca.crt, the CA certificate that lets the client validate the server’s certificate chain. The other two files are the node’s server certificate and private key; the private key stays on the server.

Your certificate directory may differ depending on your user account, base directory, and deployment method.

2. Connect with YSQL Using sslmode=require

				
					ysqlsh "sslmode=require host=127.0.0.1 user=yugabyte"
				
			

The connection succeeded:

				
					Password for user yugabyte:
ysqlsh (15.12-YB-2026.1.2.0-b0)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
				
			

That SSL message confirms an encrypted connection. It does not establish which certificate checks the client performed.

For libpq-based clients such as ysqlsh, sslmode=require requires TLS but does not require hostname verification.

There is also a compatibility detail: if a root CA file is available to libpq, require can behave like verify-ca and validate the certificate chain. A successful connection without an explicit sslrootcert argument does not prove that no CA file was used. Settings can also come from the environment or default file locations.

Use verify-full explicitly when you want both CA validation and endpoint-name verification.

Exit the YSQL session:

				
					\q
				
			

3. Try YCQL with TLS but No Configured CA File

First, try connecting with TLS enabled, but without configuring a CA certificate:

				
					ycqlsh 127.0.0.1 -u cassandra --ssl
				
			

In our test, the connection failed with:

				
					Validation is enabled; SSL transport factory requires a valid certfile to be specified.
				
			

The --ssl flag enables TLS, but ycqlsh also needs to know which CA certificate to trust. We have that file already—the ca.crt generated when we started the universe. Next, we will tell the client where to find it.

4. Point YCQL to the CA File and Reconnect

The SSL_CERTFILE environment variable tells ycqlsh where to read the CA certificate. Set it to the path identified earlier:

				
					export SSL_CERTFILE=/root/var/certs/ca.crt
				
			

Now repeat the same connection command:

				
					ycqlsh 127.0.0.1 -u cassandra --ssl
				
			

Enter the YCQL password when prompted. This time, the connection succeeds:

				
					Connected to local cluster at 127.0.0.1:9042.
[ycqlsh 5.0.1 | Cassandra 3.9-SNAPSHOT | CQL spec 3.4.2 | Native protocol v4]
Use HELP for help.
				
			

We changed only the client’s CA configuration. The client can now validate the server’s certificate chain, while the username and password still handle database login.

For repeated use, you can also configure the CA path with the certfile option in the [ssl] section of ~/.cassandra/cqlshrc. Other Cassandra-compatible clients may use different TLS settings.

🔍 CA validation and hostname validation are separate: YugabyteDB’s YCQL TLS guidance documents that the traditional ycqlsh validates the CA chain but does not check the server hostname. Do not equate a successful ycqlsh --ssl connection with YSQL’s sslmode=verify-full. Check the capabilities of the client version you deploy.

What Did the Demo Show?

ConnectionObserved resultWhat it establishes
YSQL with sslmode=requireConnected using TLS 1.3TLS was negotiated. The output alone does not prove full server identity verification.
YCQL with --ssl, no configured CA fileClient rejected the attemptCertificate validation was enabled and needed a configured trust file.
YCQL with --ssl and the correct SSL_CERTFILEConnectedThe CA file resolved the trust configuration problem. Hostname checking is a separate concern.
YCQL with --ssl and SSL_VALIDATE=falseConnected in the follow-up testTLS remains enabled, but server certificate validation is disabled.

Make YSQL Trust Explicit Too

As a follow-up test, use the same CA with verify-full:

				
					ysqlsh "host=127.0.0.1 port=5433 dbname=yugabyte user=yugabyte sslmode=verify-full sslrootcert=/root/var/certs/ca.crt"
				
			

This is an additional example, not captured output from the original run. It should succeed only when the server’s certificate chains to that CA and matches the requested address under libpq’s matching rules.

If it fails, inspect the certificate and the endpoint you are using. Fix the trust chain or certificate names rather than changing the connection back to a weaker mode just to make it connect.

Can YCQL Keep TLS Without Validating the Certificate?

Yes, with clients that support disabling verification. For ycqlsh, YugabyteDB documents the SSL_VALIDATE=false environment setting.

For an isolated local experiment, where no certificate file is configured in cqlshrc:

				
					env -u SSL_CERTFILE SSL_VALIDATE=false \
  ycqlsh 127.0.0.1 -u cassandra --ssl
				
			

The follow-up test succeeded:

				
					Password:
Connected to local cluster at 127.0.0.1:9042.
[ycqlsh 5.0.1 | Cassandra 3.9-SNAPSHOT | CQL spec 3.4.2 | Native protocol v4]
Use HELP for help.
cassandra@ycqlsh>
				
			

This confirms that this client can connect to the TLS-enabled endpoint with certificate validation disabled. The command removes SSL_CERTFILE from that process’s environment; it does not delete any certificate file or change the parent shell’s settings.

Existing cqlshrc certificate settings may still affect file loading. Unsetting SSL_CERTFILE alone does not clear those settings.

The --ssl flag retains TLS. SSL_VALIDATE=false turns off certificate validation. Using env scopes the setting to this one process instead of leaving a disabled-validation setting exported in the shell.

That setting is useful for understanding the distinction, not as a production connection template. An active attacker who can redirect or intercept traffic could impersonate the database. The connection may be encrypted to the attacker’s endpoint, exposing credentials or data to it.

Disabling TLS entirely removes transport encryption as well. If the server permits plaintext connections, queries and results become exposed on the network; YCQL password authentication can expose credentials too. If the server requires TLS, a plaintext attempt is rejected instead.

Neither disabling validation nor disabling encryption is a certificate-lifecycle solution.

Simplify Certificate Management Without Removing Trust

You often do not need to distribute a new CA certificate every time a server certificate is renewed. A replacement leaf certificate issued under an already trusted CA can usually use the existing trust configuration, provided its chain, validity, and endpoint names remain correct.

For operations, focus on these practical steps:

  • ● Use a managed trust bundle or truststore. Deploy the CA consistently to hosts, containers, or application runtimes, then point each client at the supported trust mechanism.
  • ● Plan CA rotation separately from leaf renewal. Where supported, distribute a bundle containing the old and new CA before changing server certificates; retire old trust after the transition.
  • ● Verify every endpoint the driver may use. Discovery and load balancing can introduce node addresses beyond the initial contact point.
  • ● Test reload behavior. Some clients or pools need reconnection or restart to pick up a changed trust bundle.
  • ● Keep endpoint verification enabled in application drivers that support it. Accepting a trusted certificate and checking the intended hostname are different checks.

A publicly trusted CA can reduce custom trust distribution when the client actually uses a truststore containing that CA. It does not guarantee that every driver uses the operating system’s truststore, and it does not automatically remove ycqlsh‘s configured-certfile requirement. Public certificate issuance also depends on eligible names; it is not a direct replacement for certificates for arbitrary private or loopback IP addresses.

Final Takeaway

When YSQL connects without an explicit CA path and YCQL asks for one, first compare the client verification settings.

Keep TLS enabled, configure trusted CAs deliberately, and verify endpoint identity with a client that supports it. Password authentication answers who the client is; server verification helps ensure the client sends that password to the intended database.

A successful connection is good. A trusted connection is the goal.

Have Fun!

I’ve mentioned before that YugabyteDB generously treats its employees to a DoorDash credit every Wednesday.

For the past 4½ years, mine has helped me explore the food scene around Pittsburgh. Tonight, that tradition officially made the move to our new home in the Dallas area! 🏡

The lucky winner? Goodfella’s in The Colony, serving up authentic New York style pizza right here in Texas! 🍕 And it was mighty good!

Pittsburgh to Dallas, with a little New York on the plate. Thanks, YugabyteDB! 😎