loggly-jslogger and winston-loggly-bulk are both Node.js clients designed to send application logs to the Loggly cloud service, but they serve different architectural roles. loggly-jslogger is the official, standalone HTTP client provided by Loggly, offering direct control over log transmission without requiring a specific logging framework. winston-loggly-bulk is a community-maintained transport plugin for winston, the most popular logging library in the Node.js ecosystem, designed to integrate Loggly into a unified logging strategy that may include file outputs, console debugging, and other transports simultaneously.
When integrating Loggly into a Node.js backend, architects typically face a choice between using the official standalone client or plugging Loggly into an existing Winston logging pipeline. While both achieve the end goal of getting logs into the cloud, they differ significantly in setup complexity, dependency management, and flexibility.
loggly-jslogger acts as a direct HTTP client. You instantiate a logger object specifically for Loggly and send messages to it. It does not rely on any external logging standards, meaning you are responsible for structuring your log objects.
// loggly-jslogger: Direct instantiation
const loggly = require('loggly-jslogger');
const logger = loggly.createLogger({
token: 'YOUR_LOGGLY_TOKEN',
subdomain: 'your-subdomain',
tags: ['nodejs'],
json: true
});
logger.log('User logged in', { userId: 123 });
winston-loggly-bulk functions as a "transport" within the Winston ecosystem. You configure a main Winston logger that can write to multiple places at once. Loggly becomes just one of several outputs, sharing the same log message format as your console or file logs.
// winston-loggly-bulk: Integrated transport
const winston = require('winston');
const { Loggly } = require('winston-loggly-bulk');
const logger = winston.createLogger({
transports: [
new winston.transports.Console(),
new Loggly({
token: 'YOUR_LOGGLY_TOKEN',
subdomain: 'your-subdomain',
tags: ['nodejs'],
json: true
})
]
});
logger.info('User logged in', { userId: 123 });
How you structure data before it hits Loggly differs between the two approaches.
loggly-jslogger expects you to pass objects directly. It sends exactly what you give it. This gives you raw control but requires you to manually ensure consistency across different parts of your codebase if you aren't using a standard formatter.
// loggly-jslogger: Manual object construction
const logData = {
event: 'payment_processed',
amount: 50.00,
currency: 'USD',
timestamp: new Date().toISOString()
};
logger.log(logData);
winston-loggly-bulk inherits Winston's formatting pipeline. You can define a global format (like JSON or simple text) that applies to all transports. This ensures that the log arriving in Loggly looks identical to the one printed in your local terminal, reducing context switching during debugging.
// winston-loggly-bulk: Global formatting
const { combine, timestamp, json } = winston.format;
const logger = winston.createLogger({
format: combine(
timestamp(),
json()
),
transports: [
new Loggly({ token: 'TOKEN', subdomain: 'sub' })
]
});
// Automatically includes timestamp due to global format config
logger.info('payment_processed', { amount: 50.00 });
This is the most critical factor for architectural decisions today.
loggly-jslogger is the official package maintained by Loggly (SolarWinds). It receives updates when the Loggly API changes. For new projects, this is the default recommendation to ensure compatibility and security patches are applied promptly.
winston-loggly-bulk is a community-maintained package. Historically, it has faced periods of inactivity. When Winston released version 3.0 (a major rewrite), many transport plugins broke or required significant forks to work. While this package generally works with Winston 3, it relies on community contributors to fix bugs. If your application depends heavily on specific Winston features, you risk encountering unpatched issues if the maintainer steps away.
Both packages handle network communication asynchronously, but their buffering strategies differ slightly due to their underlying design.
loggly-jslogger sends logs over HTTPS immediately upon calling .log(). For high-volume applications, you might need to implement your own batching logic if you are concerned about network chatter, though the library handles connection pooling internally.
// loggly-jslogger: Immediate send
// No built-in complex batching configuration exposed to user
logger.log('High frequency event');
winston-loggly-bulk leverages Winston's internal buffering mechanisms. Winston can buffer logs in memory before flushing them to transports, which can help smooth out spikes in log generation. However, misconfiguration here can lead to memory pressure if logs are generated faster than they can be sent to Loggly.
// winston-loggly-bulk: Inherits Winston buffering
// Controlled via winston config options if needed
const logger = winston.createLogger({
defaultMeta: { service: 'user-service' },
transports: [ new Loggly({ token: 'TOKEN' }) ]
});
If you are deploying to AWS Lambda or similar environments where cold start time and bundle size matter, loggly-jslogger is superior. You avoid pulling in the entire Winston dependency tree just to send logs to one place.
If you are running a large Express or NestJS application that already logs to files, consoles, and monitoring tools like Datadog, winston-loggly-bulk keeps your code clean. You define your logging strategy once in a central config file, and Loggly becomes just another output stream.
| Feature | loggly-jslogger | winston-loggly-bulk |
|---|---|---|
| Maintainer | Official (Loggly/SolarWinds) | Community |
| Dependencies | Minimal (Native HTTP) | Heavy (Requires Winston) |
| Setup Complexity | Low (Direct config) | Medium (Transport config) |
| Formatting | Manual / Custom | Integrated with Winston formats |
| Multi-Output | No (Single purpose) | Yes (Console, File, Loggly, etc.) |
| Best For | Serverless, Simple Services | Complex Apps, Unified Logging |
For new projects, start with loggly-jslogger. It removes the risk of relying on a third-party transport plugin that might fall out of sync with Winston updates. It is simpler, officially supported, and easier to debug since there are fewer layers between your code and the HTTP request.
Only choose winston-loggly-bulk if you are already deeply invested in the Winston ecosystem and require the ability to fan-out logs to multiple destinations with a single command. In that case, ensure you pin your dependency versions strictly to avoid breaking changes from either Winston or the transport plugin.
Choose winston-loggly-bulk if your application already relies on winston for structured logging across multiple outputs (console, file, database). This package allows you to add Loggly as just one destination in a broader logging pipeline, leveraging Winston's powerful formatting, level filtering, and metadata attachment capabilities. However, be aware that this package is community-maintained and may lag behind official Loggly API updates or Winston major version changes.
Choose loggly-jslogger if your project requires a lightweight, direct connection to Loggly without the overhead of a full logging framework like Winston. This is ideal for serverless functions (AWS Lambda, Vercel) or microservices where you want to minimize dependencies and bundle size while maintaining direct control over the HTTP payload structure. It is also the safer choice for long-term maintenance since it is officially supported by Loggly.
A Loggly transport for winston.
A client implementation for Loggly in node.js. Check out Loggly's Node logging documentation for more.
var winston = require('winston');
//
// Requiring `winston-loggly-bulk` will expose
// `winston.transports.Loggly`
//
var {Loggly} = require('winston-loggly-bulk');
winston.add(new Loggly({options}));
The Loggly transport is based on Nodejitsu's node-loggly implementation of the Loggly API. If you haven't heard of Loggly before, you should probably read their value proposition. The Loggly transport takes the following options.
true. If true, all the network errors will be logged to console.var winston = require('winston');
var { Loggly } = require('winston-loggly-bulk');
winston.add(new Loggly({
token: "TOKEN",
subdomain: "SUBDOMAIN",
tags: ["Winston-NodeJS"],
json: true
}));
winston.log('info', "Hello World from Node.js!");
This library has buffer support during temporary network outage. User can configure size of buffer (no. of logs to be stored during network outage).
Add these below configuration in code snippet to override the default values of buffer option size and retriesInMilliSeconds.
bufferOptions: {
size: 1000,
retriesInMilliSeconds: 60 * 1000
}
Our library uses ajax requests to send logs to Loggly, and as ajax requests take time to complete, logs can be lost when process.exit() is called because it forces an immediate exit. To exit gracefully and ensure that the last logs get to Loggly, we created a function called flushLogsAndExit(). It waits for 10 seconds and then calls process.exit() itself. This allows enough time for the logs to be sent to Loggly.
Here is an example of how to use the method:
var winston = require('winston');
var { flushLogsAndExit } = require('winston-loggly-bulk');
winston.log("info", "Hello World from Node.js!");
flushLogsAndExit();
tldr;?: To break the winston codebase into small modules that work together.
The winston codebase has been growing significantly with contributions and other logging transports. This is awesome. However, taking a ton of additional dependencies just to do something simple like logging to the Console and a File is overkill.
npm install winston-loggly-bulk
Note: If you are using npm version 2, please run the below command:
npm install winston-loggly-bulk winston
Written in Jest. Testing that log events are correctly passed on.
npm test